PyQt5 triggering a paintEvent() with keyPressEvent()

2024/10/5 19:16:50

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:

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!

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 sysclass Example(QWidget):paintTrigger = pyqtSignal()def __init__(self):super().__init__()self.initUI()self.ydist = 15self.eveType = "drawBlock"self.currentRegion = QRect(50,50,50,80)#self.paintTrigger[self.eveType].connect(lambda:self.paintEvent())self.x0=5self.x1=25self.y0=5self.y1=25def 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+30self.x1=self.x1+30self.y0=self.y0+30self.y1=self.y1+30def 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_())
Answer

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

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)

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.

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.

Code

class Example(QWidget):def __init__(self):super().__init__()self.mModified = Trueself.initUI()self.currentRegion = QRect(50, 50, 50, 80)self.x0 = 5self.x1 = 25self.y0 = 5self.y1 = 25self.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 = pixmapself.mModified = Falseqp = QPainter(self)qp.drawPixmap(0, 0, self.mPixmap)def drawBackground(self, qp):func, kwargs = self.funcif func is not None:kwargs["qp"] = qpfunc(**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 += 30self.x1 += 30self.y0 += 30self.y1 += 30def 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 = Trueself.update()self.nextRegion()elif gey == Qt.Key_5:print("#5 pressed, call drawNumber()")self.func = (self.drawNumber, {"notePoint": QPoint(100, 100)})self.mModified = Trueself.update()
https://en.xdnf.cn/q/70445.html

Related Q&A

A python regex that matches the regional indicator character class

I am using python 2.7.10 on a Mac. Flags in emoji are indicated by a pair of Regional Indicator Symbols. I would like to write a python regex to insert spaces between a string of emoji flags.For exampl…

Importing modules from a sibling directory for use with py.test

I am having problems importing anything into my testing files that I intend to run with py.test.I have a project structure as follows:/ProjectName | |-- /Title | |-- file1.py | |-- file2.py | …

Uploading and processing a csv file in django using ModelForm

I am trying to upload and fetch the data from csv file uploaded by user. I am using the following code. This is my html form (upload_csv1.html):<form action="{% url myapp:upload_csv %}" me…

Plotting Multiple Lines in iPython/pandas Produces Multiple Plots

I am trying to get my head around matplotlibs state machine model, but I am running into an error when trying to plot multiple lines on a single plot. From what I understand, the following code should…

libclang: add compiler system include path (Python in Windows)

Following this question and Andrews suggestions, I am trying to have liblang add the compiler system include paths (in Windows) in order for my Python codeimport clang.cindexdef parse_decl(node):refere…

Pako not able to deflate gzip files generated in python

Im generating gzip files from python using the following code: (using python 3)file = gzip.open(output.json.gzip, wb)dataToWrite = json.dumps(data).encode(utf-8)file.write(dataToWrite)file.close()Howev…

Best way to have a python script copy itself?

I am using python for scientific applications. I run simulations with various parameters, my script outputs the data to an appropriate directory for that parameter set. Later I use that data. However s…

How to convert dictionary to matrix in python?

I have a dictionary like this:{device1 : (news1, news2, ...), device2 : (news 2, news 4, ...)...}How to convert them into a 2-D 0-1 matrix in python? Looks like this:news1 news2 news3 news4 device1 …

Ubuntu 16.04 - Why I cannot install libtiff4-dev?

Following this tutorial, I am trying to install the OpenCV 3 with Python on Ubuntu 16.04.At the step of entering $ sudo apt-get install libjpeg8-dev libtiff4-dev libjasper-dev libpng12-devI got this me…

Histogram update in a for loop with matplotlib.pylab

I am trying to update in for loop a histogram data. but I dont know how to make it. I tried with set_data but it is not working. here is the code:plt.ion() ax=plt.subplot(111) [n,X, V]=ax.hist(range(MA…