I'm currently need GUI library for a project. I'm familiar with python and found PyQt might be a good choice.
I'm reading a tutorial about PyQt, and quite confused about the following example program
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
ZetCode PyQt4 tutorial
In this example, we draw text in Russian azbuka.
author: Jan Bodnar
website: zetcode.com
last edited: September 2011
"""
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.text = u'\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\
\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439: \n\
\u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430'
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Draw text')
self.show()
def paintEvent(self, event):
qp = QtGui.QPainter()
qp.begin(self)
self.drawText(event, qp)
qp.end()
def drawText(self, event, qp):
qp.setPen(QtGui.QColor(168, 34, 3))
qp.setFont(QtGui.QFont('Decorative', 10))
qp.drawText(event.rect(), QtCore.Qt.AlignCenter, self.text)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here, in main function, an Example object is created, thus __init__()
function, initUI()
is called.
My question is where does paintEvent()
function is called?? since if we run the program, self.text(some Russian letters)
will exactly appear on the widget.
In other words, what does sys.exit(app.exec_())
actually do? why it will call paintEvent()
function?
Thanks!
PyQt is widely used for creating large-scale GUI-based programs. It gives programmers the freedom to create GUIs of their choice while also providing a lot of good pre-built designs. PyQT gives you widgets to create complex GUIs.
PyQt5 is cross-platform GUI toolkit, a set of python bindings for Qt v5. One can develop an interactive desktop application with so much ease because of the tools and simplicity provided by this library. A GUI application consists of Front-end and Back-end.
Easy to master – PyQt comes with a user-friendly, straightforward API functionality, along with specific classes linked to Qt C++. This allows the user to use previous knowledge from either Qt or C++, making PyQt easy to understand.
What is PyQt5? PyQt is a library that lets you use the Qt GUI framework from Python. Qt itself is written in C++. By using it from Python, you can build applications much more quickly while not sacrificing much of the speed of C++. PyQt5 refers to the most recent version 5 of Qt.
From PyQt docs:
int QApplication.exec_ ()
Enters the main event loop and waits until
exit()
is called, then returns the value that was set toexit()
(which is 0 ifexit()
is called viaquit()
).It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets.
From another source:
sys.exit(app.exec_())
Finally, we enter the mainloop of the application. The event handling starts from this point. The mainloop receives events from the window system and dispatches them to the application widgets. The mainloop ends, if we call the
exit()
method or the main widget is destroyed. Thesys.exit()
method ensures a clean exit. The environment will be informed, how the application ended.The
exec_()
method has an underscore. It is because theexec
is a Python keyword. And thus,exec_()
was used instead.
About painting:
4.2.1. When Painting Occurs
The
paintEvent()
method is called automatically when
Your widget is shown for the first time.
After a window has been moved to reveal some part (or all) of the widget.
The window in which the widget lies is restored after being minimized.
The window in which the widget lies is resized.
The user switches from another desktop to the desktop on which the widget's window lies.
You can generate paint events manually by calling
QWidget::update()
.QWidget::update()
erases the widget before generating the paint event. You can pass arguments toupdate()
, which can restrict painting only to areas (rectangles, in particular) that need it. The two equivalent forms of the method areQWidget::update (int x, int y, int width, int height)
andQWidget::update (QRect rectangle)
, wherex
andy
give the upper-left corner of the rectangle, and width and height are obvious. Becauseupdate()
places a paint event into the event queue, no painting occurs until the current method exits and control returns to the event handler. This is a good thing because other events may be waiting there to be processed, and events need to be processed in a timely manner for the GUI to operate smoothly.You can also invoke painting of the widget by calling
QWidget::repaint (int x, int y, int width, int height, bool erase)
(or one of several convenience-method forms), where all the arguments mean the same as in the case of theupdate()
method, and erase tells repaint whether to erase the rectangle before painting it.repaint()
callspaintEvent()
directly. It does not place a paint event into the event queue, so use this method with care. If you try to callrepaint()
repeatedly from a simple loop to create an animation, for example, the animation will be drawn, but the rest of your user interface will be unresponsive because the events corresponding to mouse button clicks, keyboard presses, and so on will be waiting in the queue. Even if you are not performing a task as potentially time-consuming as animation, it is generally better to useupdate()
to help keep your GUI alive.If you paint something on your widget outside the
paintEvent()
, you still need to include the logic and commands necessary to paint that same thing inpaintEvent()
. Otherwise, the painting you did would disappear the next time the widget is updated.
It becomes more clear when one has some experience with low level programming, for example in Winapi or the X toolkit in C language. PyQt is a (very) high level toolkit. It comes with a huge built-in functionality. Similar example would require hundreds or maybe thousands of lines of C code. As a consequence, there is a lot of going on behind the scenes. Somebody already created code that deals with painting on a basic level. GUI programming is very complex and with modern GUI toolkits the application programmer is shielded from this complexity. It is inevitable that programmers are confused if they do not know all the technical details.
In PyQt, we are essentially dealing with events in two ways. We connect signals to slots or reimplement event handlers (an event handler is a synonym for a slot). The provided example inherited from the QtGui.QWidget
which already has some painting code available.
In order to do our custom painting, we have to reimplement the existing paintEvent()
event
handler. Depending on the situation, we may or may not call the parent's paintEvent()
method.
The sys.exit(app.exec_())
does not call the paintEvent()
method. The exec_()
method starts an event loop. The event loop catches and dispatches events. Paint events are triggered by users or by the operating system. For example, when we launch the example, the
paint event is triggered twice. (Put a print "Event occurred"
line in the event handler to see how many times this method is called.) Resizing windows, loosing or gaining focus, minimizing or maximizing windows, all these cause painting events to be triggered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With