PyQt5 使用 keyPressEvent() 触发paintEvent() [英] PyQt5 triggering a paintEvent() with keyPressEvent()

查看:117
本文介绍了PyQt5 使用 keyPressEvent() 触发paintEvent()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 PyQt 矢量绘画.目前我一直在尝试将信息传递给我猜应该调用其他方法的paintEvent()方法:

I am trying to learn PyQt vector painting. Currently I am stuck in trying to pass information to paintEvent() method which I guess, should call other methods:

我试图将不同的数字绘制到一个基本块(这里是 drawFundBlock() 方法,它应该绘制一些线条).代码试图检查是否按下了右箭头-> drawFundamental 块,如果按下了数字(现在尝试简单地绘制5"),它将在该基本块的某个区域上绘制该数字.但我似乎无法让 QPainter 工作.现在它似乎调用了paintEvent() 覆盖方法两次(为什么?).有些人建议使用 update() 方法,但我不知道如何将任何参数传递给paintEvent(),它应该确定是绘制fundblock"还是number".现在代码使用 update() 进行演示,但这只是移动行 - 但已经添加的行应该保留!

I am trying to paint different numbers to a fundamental block (here drawFundBlock() method, which should draw some lines). 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. But I can't seem to get the QPainter to work. It seems it's calling the paintEvent() override method twice now (why?). 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". Now the code uses update() for demonstration but this simply moves the lines - But the already Added Lines should remain!

有什么帮助吗?

# 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 不应该直接调用,必须通过update()来调用,这需要必要时注意在内部调用它.

QPaintEvent should not be called directly, we must do it through update(), this will take care of calling it internally when necessary.

每次 QPaintEvent 被调用时,这个干净的空间是它要绘制的空间,所以它不会节省之前绘制的内存,一个简单的解决方案是先绘制一个 QPixmap 它将存储您之前绘制的内容,然后使用该 QPixmap 绘制小部件.

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.

另一件事是以下两条指令是等效的:

Another thing is that the following 2 instructions are equivalent:

1.

painter = QPainter(some_QPaintDevice)

<小时>

2.

painter = QPainter()
painter.begin(some_QPaintDevice)

<小时>

这两种方法都用于传递将要绘制的对象,在您的情况下,您分配了 2 次相同的小部件.


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.

为了绘图方便我提出了drawBackground方法,这个方法需要填self.func,第一个参数必须是函数名和第二个字典包含除了 QPainter 之外所需的参数.

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.

代码

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()

这篇关于PyQt5 使用 keyPressEvent() 触发paintEvent()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆