简体   繁体   English

PyQt5使用keyPressEvent()触发paintEvent()

[英]PyQt5 triggering a paintEvent() with keyPressEvent()

I am trying to learn PyQt vector painting. 我正在尝试学习PyQt矢量绘画。 Currently I am stuck in trying to pass information to paintEvent() method which I guess, should call other methods: 目前,我一直在尝试将信息传递给paintEvent()方法,我猜应该调用其他方法:

I am trying to paint different numbers to a fundamental block (here drawFundBlock() method, which should draw some lines). 我正在尝试将不同的数字绘制到基本块(此处为drawFundBlock()方法,该方法应绘制一些线)。 The code is trying to check if right arrow is pressed-> drawFundamental block and if number is pressed (now trying to simply draw "5"), it will draw that number on a certain area on that fundamental block. 该代码试图检查是否按下了右箭头-> drawFundamental块,并且如果按下了数字(现在试图简单地绘制“ 5”),它将在该基本块的某个区域上绘制该数字。 But I can't seem to get the QPainter to work. 但是我似乎无法使QPainter正常工作。 It seems it's calling the paintEvent() override method twice now (why?). 似乎现在两次调用paintEvent()覆盖方法(为什么?)。 Some people have suggested the update() method, but I have no idea how to still pass any arguments to paintEvent(), which should determine whether to draw "fundblock" or "number". 有人建议使用update()方法,但我不知道如何仍然将任何参数传递给paintEvent(),后者应确定是绘制“ fundblock”还是“ number”。 Now the code uses update() for demonstration but this simply moves the lines - But the already Added Lines should remain! 现在,代码使用update()进行演示,但这只是移动了行-但已经添加的行应该保留!

Any help? 有什么帮助吗?

# Test QPainter etc.

from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QPen, QColor, QFont
from PyQt5.QtCore import Qt, QPoint, pyqtSignal, QRect
import sys

class Example(QWidget):

    paintTrigger = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.initUI()
        self.ydist = 15
        self.eveType = "drawBlock"
        self.currentRegion = QRect(50,50,50,80)
        #self.paintTrigger[self.eveType].connect(lambda:self.paintEvent())

        self.x0=5
        self.x1=25
        self.y0=5
        self.y1=25

    def initUI(self):
        self.setGeometry(300,300,280,270)
        self.setWindowTitle('Painter training')
        self.show()

    # How to pass info here, which type of drawing should be done (block or number)?
    def paintEvent(self,event):
        qp = QPainter(self)
        qp.begin(self)  
        self.drawFundBlock(qp)
        qp.end()

    def drawFundBlock(self,qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        pen.setStyle(Qt.DashLine)

        qp.setPen(pen)
        for i in range(1,10):
            #qp.drawLine(0,i*self.ydist,40,i*self.ydist)
            qp.drawLine(self.x0,i*self.y0,self.x1,self.y0*i)

        #notePoint=QPoint(200,200)
        #qp.drawText(notePoint,"5")

    def drawNumber(self,qp,notePoint):
        pen = QPen(Qt.black,2,Qt.SolidLine)
        #qp.setPen(QColor(200,200,200))
        qp.setPen(pen)
        qp.setFont(QFont('Arial', 10))
        qp.drawText(notePoint,"5")

    def nextRegion(self):
        self.x0=self.x0+30
        self.x1=self.x1+30
        self.y0=self.y0+30
        self.y1=self.y1+30

    def keyPressEvent(self,event):
        # Did the user press a button??
        gey=event.key()
        if gey == Qt.Key_M: 
            print("Key 'm' pressed!")
        elif gey == Qt.Key_Right:
            print("Right key pressed!, call drawFundBlock()")
            #self.paintTrigger["drawBlock"].emit()
            #self.paintEvent()
            self.update()
            self.nextRegion()

        elif gey == Qt.Key_5:
            print("#5 pressed, call drawNumber()")
            #self.paintTrigger["drawNo"].emit()


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

QPaintEvent should not be called directly, we must do it through update() , this will take care of calling it internally when necessary. QPaintEvent不应直接调用,我们必须通过update() ,这将在必要时进行内部调用。

Each time QPaintEvent is called this clean is space where it is going to draw so it does not save memory of the previous drawings, a simple solution is to first paint a QPixmap where it will store what you have painted previously and then paint the widget with that QPixmap . 每次调用QPaintEvent时, QPaintEvent在此干净的空间中进行绘制,因此不会节省以前的图形的内存,一种简单的解决方案是首先绘制一个QPixmap ,它将存储您先前绘制的内容,然后使用那个QPixmap

Another thing is that the following 2 instructions are equivalent: 另一件事是,以下2条指令是等效的:

1. 1。


painter = QPainter(some_QPaintDevice)

2. 2。


painter = QPainter()
painter.begin(some_QPaintDevice)

Both methods serve to pass the object where it is going to be painted, and in your case you are assigning 2 times the same widget. 这两种方法都将对象传递到将要绘制对象的位置,在您的情况下,您将分配相同的小部件2倍。

To facilitate the drawing I have proposed the method drawBackground , this method needs to be filled with self.func , the first parameter must be the name of the function and the second a dictionary with the parameters that are needed except the QPainter . 为了方便绘图,我提出了方法drawBackground ,该方法需要用self.func填充,第一个参数必须是函数的名称,第二个参数是具有字典的字典,除了QPainter之外,还需要其他参数。

Code

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.mModified = True
        self.initUI()
        self.currentRegion = QRect(50, 50, 50, 80)
        self.x0 = 5
        self.x1 = 25
        self.y0 = 5
        self.y1 = 25
        self.mPixmap = QPixmap()
        self.func = (None, None)

    def initUI(self):
        self.setGeometry(300, 300, 280, 270)
        self.setWindowTitle('Painter training')
        self.show()

    def paintEvent(self, event):
        if self.mModified:
            pixmap = QPixmap(self.size())
            pixmap.fill(Qt.white)
            painter = QPainter(pixmap)
            painter.drawPixmap(0, 0, self.mPixmap)
            self.drawBackground(painter)
            self.mPixmap = pixmap
            self.mModified = False

        qp = QPainter(self)
        qp.drawPixmap(0, 0, self.mPixmap)

    def drawBackground(self, qp):
        func, kwargs = self.func
        if func is not None:
            kwargs["qp"] = qp
            func(**kwargs)

    def drawFundBlock(self, qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        pen.setStyle(Qt.DashLine)

        qp.setPen(pen)
        for i in range(1, 10):
            qp.drawLine(self.x0, i * self.y0, self.x1, self.y0 * i)

    def drawNumber(self, qp, notePoint):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        qp.setPen(pen)
        qp.setFont(QFont('Arial', 10))
        qp.drawText(notePoint, "5")

    def nextRegion(self):
        self.x0 += 30
        self.x1 += 30
        self.y0 += 30
        self.y1 += 30

    def keyPressEvent(self, event):
        gey = event.key()
        self.func = (None, None)
        if gey == Qt.Key_M:
            print("Key 'm' pressed!")
        elif gey == Qt.Key_Right:
            print("Right key pressed!, call drawFundBlock()")
            self.func = (self.drawFundBlock, {})
            self.mModified = True
            self.update()
            self.nextRegion()
        elif gey == Qt.Key_5:
            print("#5 pressed, call drawNumber()")
            self.func = (self.drawNumber, {"notePoint": QPoint(100, 100)})
            self.mModified = True
            self.update()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM