PyQT5 - 如何一起使用 QWidget、QScrollArea 和 QBrush

问题描述 投票:0回答:1

我正在努力:

  1. 显示大于窗口大小的图像;
  2. 使窗口可滚动,这样我就可以滚动浏览整个图像;
  3. 在图像上画画;

问题是:

  1. 一旦我使窗口可滚动,我就再也看不到绘图了;

我该如何解决?

最小的例子:

class DocumentWindow(QWidget):
    def __init__(self, main_obj):
        super().__init__()

        self.WIDTH = 500
        self.HEIGHT = 500
        self.resize(self.WIDTH, self.HEIGHT)

        file_path = 'invoice_example.jpeg'
        self.pages = {0: Image.open(file_path)}
        image = QImage(file_path)
        self.doc_original_width = image.width()
        self.doc_original_height = image.height()
        self.doc_new_width = image.width()
        self.doc_new_height = image.height()
        palette = QPalette()
        palette.setBrush(QPalette.Window, QBrush(image))
        self.setPalette(palette)
        label = QLabel(None, self)
        label.setGeometry(0, 0, self.WIDTH, self.HEIGHT)

        conWin = QWidget()
        conLayout = QVBoxLayout(self)
        conLayout.setContentsMargins(0, 0, 0, 0)
        conWin.setLayout(conLayout)
        scroll = QScrollArea()
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setWidgetResizable(True)
        scroll.setWidget(conWin)
        scrollLayout = QVBoxLayout(self)

        # When I enable these lines, I got no visible drawing
        scrollLayout.addWidget(scroll)
        scrollLayout.setContentsMargins(0, 0, 0, 0)

        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()
        self.show()
    
    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        br = QtGui.QBrush(QtGui.QColor(100, 10, 10, 40))  
        qp.setBrush(br)   
        qp.drawRect(QtCore.QRect(self.begin, self.end))
        rect = QtCore.QRect(self.begin, self.end)
        self.coordinates = rect.getCoords()

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = event.pos()
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        x1, y1, x2, y2 = self.coordinates
        if x1 == x2 or y1 == y2:
            return
        self.width_factor = self.doc_original_width / self.doc_new_width
        self.height_factor = self.doc_original_height / self.doc_new_height
        self.normalized_coordinates = [ 
            int(x1*self.width_factor), int(y1*self.height_factor),
            int(x2*self.width_factor), int(y2*self.height_factor) ]
        self.update()
    
python pyqt pyqt5
1个回答
1
投票

问题是您将滚动区域放在

DocumentWindow
小部件的顶部(您的事件处理程序在此处重新实现),因此绘图隐藏在它下面。您仍然可以看到图像,因为 QScrollArea(和其他小部件)如果未明确设置(并且您正在通过调色板显示图像),则继承其父级的
backgroundRole

绘图需要在 QScrollArea 的

widget
中实现,它现在是一个空的 QWidget
conWin
。对于您的示例,这可以通过使 QScrollArea 成为顶级小部件并将
DocumentWindow
实例设置为滚动区域的
widget
.

来简化

minimumSizeHint
被添加以通过为小部件设置推荐的最小尺寸来支持滚动功能。

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class DocumentWindow(QWidget):

    def __init__(self):
        super().__init__()
        file_path = 'invoice_example.jpeg'
        self.image = QImage(file_path)
        palette = QPalette()
        palette.setBrush(QPalette.Window, QBrush(self.image))
        self.setPalette(palette)
        self.begin = QPoint()
        self.end = QPoint()

    def minimumSizeHint(self):
        return self.image.size()

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = event.pos()
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        x1, y1, x2, y2 = QRect(self.begin, self.end).getCoords()
        if x1 == x2 or y1 == y2:
            return
        self.update()
        
    def paintEvent(self, event):
        qp = QPainter(self)        
        br = QBrush(QColor(100, 10, 10, 40))  
        qp.setBrush(br)   
        qp.drawRect(QRect(self.begin, self.end))


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    
    scroll = QScrollArea()
    scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    scroll.setWidgetResizable(True)
    scroll.setWidget(DocumentWindow())
    scroll.resize(500, 500)
    scroll.show()
    
    sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.