PyQt5:绘制新的时保持以前绘制的drawings/line

PyQt5: Maintain previously drawn drawings/line when new ones are drawn

我在绘制一条新线后无法维护之前绘制的线。现在,如果我单击一个按钮,它会画一条线,但是一旦我单击第二个按钮,就会绘制一条新线,并删除最初的那条线。我希望两者都保留。

import sys
from PyQt5.QtWidgets import QMainWindow,QPushButton, QApplication
from PyQt5.QtCore import QSize, Qt, QLine, QPoint
from PyQt5.QtGui import QPainter, QPen

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(300, 300)) 

        pybutton = QPushButton('button', self)
        pybutton.clicked.connect(self.draw_line)
        pybutton.resize(100,100)
        pybutton.move(0, 0) 

        pybutton2 = QPushButton('button2', self)
        pybutton2.clicked.connect(self.draw_line)
        pybutton2.resize(100,100)
        pybutton2.move(200, 0) 
        self.line = QLine()

    def draw_line(self):
        button = self.sender()
        x = int(button.x()) + int(button.width())/2
        y = int(button.y())+100
        self.line = QLine(x, y, x, y+100)
        self.update()

    def paintEvent(self,event):
        QMainWindow.paintEvent(self, event)
        if not self.line.isNull():
            painter = QPainter(self)
            pen = QPen(Qt.red, 3)
            painter.setPen(pen)
            painter.drawLine(self.line)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

简短的解决方案:

QLine 存储在列表中并重绘:

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(300, 300)) 

        pybutton = QPushButton('button', self)
        pybutton.clicked.connect(self.draw_line)
        pybutton.resize(100,100)
        pybutton.move(0, 0) 

        pybutton2 = QPushButton('button2', self)
        pybutton2.clicked.connect(self.draw_line)
        pybutton2.resize(100,100)
        pybutton2.move(200, 0) 
        self.lines = []

    def draw_line(self):
        button = self.sender()
        r = button.geometry()
        p1 = QPoint(r.left() + r.width()/2, r.height())
        p2 = p1+QPoint(0, 100)
        line = QLine(p1, p2)
        if line not in self.lines:
            self.lines.append(line)
            self.update()

    def paintEvent(self,event):
        QMainWindow.paintEvent(self, event)
        painter = QPainter(self)
        pen = QPen(Qt.red, 3)
        painter.setPen(pen)
        for line in self.lines:
            painter.drawLine(line)

长解:

这类问题已经被问过无数次了,所以我会花时间展开并给出问题的一般观点,这样我就不会每次都回答这类问题,所以这个问题 会不断完善和更新。

paintEvent()是处理Qt重绘GUI的方法,该方法重绘所有内容,因此绘图不节省内存,所以必须存储指令并进行绘图 按照这些说明。

我推荐使用的paintEvent()方法来创建自定义小部件,而不是制作一个以执行绘画任务作为主要功能的GUI,为此Qt提供了classQGraphicsViewQGraphicsSceneQGraphicsItems.


使用QPainter的指令进行重绘任务,因为drawLine()fillRect()等会消耗资源,如果你想更高效的实现,创建一个是合适的QPixmap 您必须在必要时更新,并使用提到的 QPixmap:

paintEvent() 中重新绘制
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(300, 300)) 

        pybutton = QPushButton('button', self)
        pybutton.clicked.connect(self.draw_line)
        pybutton.resize(100,100)
        pybutton.move(0, 0) 

        pybutton2 = QPushButton('button2', self)
        pybutton2.clicked.connect(self.draw_line)
        pybutton2.resize(100,100)
        pybutton2.move(200, 0)
        self.pixmap = QPixmap(self.size())
        self.pixmap.fill(Qt.transparent)

    def draw_line(self):
        button = self.sender()
        r = button.geometry()
        p1 = QPoint(r.left() + r.width()/2, r.height())
        p2 = p1+QPoint(0, 100)
        line = QLine(p1, p2)

        p = QPainter(self.pixmap)
        pen = QPen(Qt.red, 3)
        p.setPen(pen)
        p.drawLine(line)
        p.end()

        self.update()

    def paintEvent(self,event):
        QMainWindow.paintEvent(self, event)
        painter = QPainter(self)
        painter.drawPixmap(QPoint(), self.pixmap)

    def resizeEvent(self, event):
        if self.width() > self.pixmap.width() or self.height() > self.pixmap.height():
            pixmap = QPixmap(self.size())
            pixmap.fill(Qt.transparent)
            p = QPainter(pixmap)
            p.drawPixmap(QPoint(), self.pixmap)
            self.pixmap = pixmap
        QMainWindow.resizeEvent(self, event)