我目前需要一个项目的GUI库。我熟悉python,发现PyQt可能是个不错的选择。
我正在阅读a tutorial about PyQt,并对以下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()
这里,在main函数中,创建了一个Example对象,因此调用了__init__()
函数initUI()
。
我的问题是paintEvent()
函数在哪里被调用?因为如果我们运行程序,self.text(some Russian letters)
将完全出现在小部件上。
换句话说,sys.exit(app.exec_())
实际上做了什么?为什么它会调用paintEvent()
函数?
谢谢!
答案 0 :(得分:8)
来自PyQt docs:
int QApplication.exec_ ()
进入主事件循环并等待
exit()
被调用,然后 返回设置为exit()
的值(如果exit()
为0则为0 通过quit()
)调用。必须调用此函数才能启动事件处理。该 主事件循环从窗口系统接收事件并发送 这些应用程序小部件。
sys.exit(app.exec_())
最后,我们进入了主循环 应用。事件处理从这一点开始。主循环 从窗口系统接收事件并将它们发送到 应用程序小部件。如果我们调用
exit()
方法,则主循环结束 或主要小部件被销毁。sys.exit()
方法可确保清洁 出口。将通知环境,应用程序如何结束。
exec_()
方法有下划线。这是因为exec
是一个 Python关键字。因此,改为使用exec_()
。
关于painting:
<强> 4.2.1。当绘画发生时
时会自动调用
paintEvent()
方法
您的小部件首次显示。
移动窗口后显示部分(或全部) 窗口小部件。
小部件所在的窗口在最小化后恢复。
调整小部件所在的窗口的大小。
用户从另一个桌面切换到桌面上 小部件的窗口在于。
您可以通过调用
QWidget::update()
手动生成绘画事件。QWidget::update()
在生成绘制事件之前擦除小部件。 您可以将参数传递给update()
,这可以仅限制绘画 到需要它的区域(特别是矩形)。两个相当 该方法的形式为QWidget::update (int x, int y, int width, int height)
和QWidget::update (QRect rectangle)
,其中x
和y
给出了 矩形的左上角,宽度和高度都很明显。 因为update()
将一个绘制事件放入事件队列中,所以没有 绘制发生,直到当前方法退出并且控制返回 事件处理程序。这是一件好事,因为其他事件可能是 等待处理,需要处理事件 及时使GUI顺利运行。您还可以通过调用
QWidget::repaint (int x, int y, int width, int height, bool erase)
(或其中一个)来调用窗口小部件的绘制 方便方法形式),其中所有参数与in中的相同update()
方法的情况,擦除告诉重绘是否 在绘制之前擦除矩形。repaint()
来电paintEvent()
直。它不会将paint事件放入事件队列中,因此请使用 这种方法要小心。如果您尝试反复拨打repaint()
用于创建动画的简单循环,例如,动画将是 已绘制,但您的用户界面的其余部分将无法响应 因为鼠标按键对应的事件,键盘 按,等等将在队列中等待。即使你不是 执行任务可能像动画一样耗费时间 通常最好使用update()
来帮助保持GUI的活跃。如果您在
paintEvent()
之外的小部件上绘制某些内容,则表示您 仍然需要包含绘制它所需的逻辑和命令paintEvent()
中同样的事情。否则,你做的画会 下次更新小部件时消失。
答案 1 :(得分:1)
app.exec_()
启动qt主循环,该循环在每个创建的小部件被销毁时结束(例如,通过关闭其窗口)。 paintEvent
函数是一个方法,您可以从QWidget
子类重载,如给定的Example
类,当QT显示,更新或重新绘制Widget时,它会被调用。
您可以在Qt documentation或PyQt Documentation中查找这些内容(这些内容大多只是QT文档的副本,格式不同,但有时会包含一些有关PyQt特定内容的重要信息)。
答案 2 :(得分:1)
当一个人有一些低级编程经验时,会变得更加清晰 例如在Winapi或C语言的X工具包中。 PyQt是一个(非常)高级工具包。 它具有巨大的内置功能。类似的例子需要数百甚至数千行C代码。因此,有很多事情要发生 在幕后。有人已经创建了在基本级别处理绘画的代码。 GUI编程非常复杂,使用现代GUI工具包,应用程序员可以避免这种复杂性。如果程序员不了解所有技术细节,那就不可避免地会感到困惑。
在PyQt中,我们基本上以两种方式处理事件。我们将信号连接到插槽或重新实现事件处理程序(事件处理程序是插槽的同义词)。提供的示例继承自QtGui.QWidget
,其中已有一些绘制代码可用。
为了进行自定义绘画,我们必须重新实现现有的paintEvent()
事件
处理程序。根据具体情况,我们可能会或可能不会调用父母的paintEvent()
方法。
sys.exit(app.exec_())
未调用paintEvent()
方法。 exec_()
方法启动事件循环。事件循环捕获和分派事件。绘制事件由用户或操作系统触发。例如,当我们启动示例时,
paint事件被触发两次。 (在事件处理程序中放置一个print "Event occurred"
行,以查看调用此方法的次数。)调整窗口大小,放松或获得焦点,最小化或最大化窗口,所有这些都会导致绘制事件被触发。