Отображение изображения под строкой меню в PyQt

У меня простой поток: пользователь нажимает кнопку, появляется всплывающее окно QDialog, и я хочу отобразить MenuBar и изображение под MenuBar (рендеринг происходит во время paintEvent).

import sys

from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QDialog, QMenuBar, QAction, QHBoxLayout


class Example(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.button = QPushButton()
        self.button.setText("Click")
        self.button.setMaximumHeight(100)
        self.button.setMaximumWidth(100)
        self.button.clicked.connect(self.clicked)

        self.layout().addWidget(self.button)

        self.show()

    def clicked(self):
        self.something = SecondExample()
        self.something.exec()

class SecondExample(QDialog):
    def __init__(self):
        super().__init__()
        self.installEventFilter(self)

        layout = QHBoxLayout()

        toolbar = QMenuBar()
        toolbar.addAction(QAction("Edit", toolbar))
        toolbar.addAction(QAction("Polygon", toolbar))
        toolbar.addAction(QAction("Rectangle", toolbar))

        layout.setMenuBar(toolbar)

        self.setLayout(layout)

        self.pixmap = QPixmap(r"C:\Users\kjankosk\Desktop\Panasonic-OLED-TV-FZ950-Lifestyle.jpg")
        self.resize(self.pixmap.width(), self.pixmap.height())


    def paintEvent(self, event):
        super().paintEvent(event)

        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)

        painter.drawPixmap(self.rect(), self.pixmap)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Вот воспроизводимый пример того, что у меня есть (редактируйте путь к изображению), однако часть изображения появляется за строкой меню. Как я могу решить эту проблему? Я думаю, что основная проблема связана с вызовом rect(), поскольку он, кажется, использует все окно, но я надеялся, что строка меню будет «вне окна».


person Kristijan    schedule 19.06.2019    source источник


Ответы (2)


Возможное решение состоит в том, чтобы указать смещение, подобное тому, которое указано S.Nick, но, как вы видели, первым недостатком является для вычисления смещения, зависящего от стиля и ОС. Поэтому другое возможное решение — создать еще один виджет, в котором отображается изображение, и добавить его в макет:

# ...
class Widget(QWidget):
    def __init__(self):
        super().__init__()

        self.pixmap = QPixmap(
            r"C:\Users\kjankosk\Desktop\Panasonic-OLED-TV-FZ950-Lifestyle.jpg"
        )

    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.drawPixmap(self.rect(), self.pixmap)

    def sizeHint(self):
        return self.pixmap.size()


class SecondExample(QDialog):
    def __init__(self):
        super().__init__()

        layout = QHBoxLayout(self)

        toolbar = QMenuBar()
        toolbar.addAction(QAction("Edit", toolbar))
        toolbar.addAction(QAction("Polygon", toolbar))
        toolbar.addAction(QAction("Rectangle", toolbar))

        layout.setMenuBar(toolbar)

        widget = Widget()
        layout.addWidget(widget)
# ...
person eyllanesc    schedule 19.06.2019
comment
Это то, что я пытался сделать, но по какой-то причине он не изменил свой размер, работает с sizeHint. Спасибо. - person Kristijan; 20.06.2019
comment
Я только что попробовал увеличить изображение, и все равно кажется, что оно сжимает высоту на смещение в зависимости от размера панели инструментов. - person Kristijan; 20.06.2019
comment
@Kristijan Какой у тебя размер изображения? если бы вы могли поделиться изображением, чтобы проанализировать, в чем проблема, и, таким образом, улучшить мое решение, было бы здорово - person eyllanesc; 20.06.2019
comment
Изображение, которое я пробовал, имеет размер 892 x 852 пикселей — я могу отправить его вам, если это необходимо. - person Kristijan; 20.06.2019
comment
@Kristijan Вы также можете поделиться скриншотом своего окна, чтобы лучше понять вашу проблему. - person eyllanesc; 20.06.2019
comment
imgur.com/a/XYmX1pg здесь параллельное сравнение (слева — решение) - person Kristijan; 20.06.2019

Попытайся:

import sys
from PyQt5 import QtGui
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (QMainWindow, QApplication, QPushButton, QDialog, 
                             QMenuBar, QAction, QHBoxLayout, QWidget, QGridLayout)

class SecondExample(QDialog):
    def __init__(self):
        super().__init__()
        self.installEventFilter(self)

        toolbar = QMenuBar()
        toolbar.addAction(QAction("Edit", toolbar))
        toolbar.addAction(QAction("Polygon", toolbar))
        toolbar.addAction(QAction("Rectangle", toolbar))

        layout = QHBoxLayout()
        layout.setMenuBar(toolbar)
        self.setLayout(layout)

        self.pixmap = QPixmap("D:/_Qt/__Qt/img/max1.jpg")      # py-qt.png
        self.resize(self.pixmap.width(), self.pixmap.height())

    def paintEvent(self, event):
        super().paintEvent(event)

        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)

#        painter.drawPixmap(self.rect(), self.pixmap)
        rect = self.rect().x(), self.rect().y()+20, self.rect().width(), self.rect().height()-20 # +++
        painter.drawPixmap(*rect, self.pixmap)                                                   # +++


class Example(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.button = QPushButton(self)
        self.button.setText("Click")
        self.button.setMaximumHeight(100)
        self.button.setMaximumWidth(100)
        self.button.clicked.connect(self.clicked)

        centralWidget = QWidget()
        self.setCentralWidget(centralWidget)
        layout = QGridLayout(centralWidget)
#        self.layout().addWidget(self.button)
        layout.addWidget(self.button)

    def clicked(self):
        self.something = SecondExample()
        self.something.show()            # exec()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

введите здесь описание изображения

person S. Nick    schedule 19.06.2019
comment
Ну да, это очевидное решение, но это означает, что rect() теперь смещается на фиксированную величину - вероятно, есть способ сделать панель меню не частью rect(). Потенциальная проблема заключается в том, что мне пришлось бы также сместить координаты положения мыши, скажем, если бы я поймал ее, поскольку она не давала бы правильных позиций из-за наличия строки меню. - person Kristijan; 19.06.2019