9

我目前需要一个项目的 GUI 库。我熟悉 python,发现 PyQt 可能是一个不错的选择。

我正在阅读有关 PyQt 的教程,并且对以下示例程序感到非常困惑

#!/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()函数?

谢谢!

4

3 回答 3

8

来自PyQt 文档

int QApplication.exec_ ()

进入主事件循环并等待直到exit()被调用,然后返回设置为的值(如果通过 调用exit(),则为 0 )。exit()quit()

需要调用此函数来启动事件处理。主事件循环从窗口系统接收事件并将这些事件分派给应用程序小部件。

另一个来源

sys.exit(app.exec_())

最后,我们进入应用程序的主循环。事件处理从这一点开始。主循环从窗口系统接收事件并将它们分派给应用程序小部件。如果我们调用该exit()方法或主小部件被销毁,则主循环结束。该sys.exit()方法确保干净的出口。将通知环境,应用程序如何结束。

exec_()方法有一个下划线。这是因为exec是 Python 关键字。因此,exec_()改为使用。

关于绘画

4.2.1。当绘画发生时

paintEvent()方法在以下情况下被自动调用

  • 您的小部件首次显示。

  • 在移动窗口以显示小部件的某些部分(或全部)之后。

  • 小部件所在的窗口在最小化后恢复。

  • 小部件所在的窗口被调整大小。

  • 用户从另一个桌面切换到小部件窗口所在的桌面。

您可以通过调用手动生成绘制事件QWidget::update()QWidget::update()在生成绘制事件之前擦除小部件。您可以将参数传递给update(),这可以将绘画限制在需要它的区域(特别是矩形)。该方法的两种等效形式是QWidget::update (int x, int y, int width, int height)QWidget::update (QRect rectangle),其中xy给出了矩形的左上角,宽度和高度是显而易见的。因为update()将绘制事件放入事件队列中,所以在当前方法退出并且控制返回到事件处理程序之前不会进行绘制。这是一件好事,因为其他事件可能正在那里等待处理,并且需要及时处理事件以使 GUI 顺利运行。

您还可以通过调用QWidget::repaint (int x, int y, int width, int height, bool erase)(或几种便捷方法形式之一)来调用小部件的绘制,其中所有参数的含义与update()方法的情况相同,并且 erase 告诉 repaint 是否在绘制矩形之前擦除它。repaint()直接调用paintEvent() 。它不会将绘制事件放入事件队列中,因此请谨慎使用此方法。如果你试图repaint()从一个简单的循环中重复调用来创建一个动画,例如,动画将被绘制,但你的用户界面的其余部分将无响应,因为对应于鼠标按钮单击、键盘按下等的事件将在队列中等待。即使您没有执行像动画那样可能耗时的任务,通常也最好使用update()帮助保持你的 GUI 活着。

如果您paintEvent()paintEvent(). 否则,您所做的绘画将在下次更新小部件时消失。

于 2012-08-04T05:16:17.833 回答
1

当一个人有一些低级编程经验时会变得更加清楚,例如在 Winapi 或 C 语言中的 X 工具包中。PyQt 是一个(非常)高级的工具包。它具有巨大的内置功能。类似的示例将需要数百甚至数千行 C 代码。因此,幕后发生了很多事情。有人已经创建了处理基本绘画的代码。GUI 编程非常复杂,使用现代 GUI 工具包,应用程序程序员可以免受这种复杂性的影响。如果不了解所有技术细节,程序员难免会感到困惑。

在 PyQt 中,我们基本上以两种方式处理事件。我们将信号连接到槽或重新实现事件处理程序(事件处理程序是槽的同义词)。提供的示例继承自QtGui.QWidgetwhich 已经有一些可用的绘画代码。为了进行自定义绘制,我们必须重新实现现有的paintEvent()事件处理程序。根据情况,我们可能会也可能不会调用父类的paintEvent()方法。

sys.exit(app.exec_())不调用该方法paintEvent()。该exec_()方法启动一个事件循环。事件循环捕获并分派事件。绘制事件由用户或操作系统触发。例如,当我们启动示例时,会触发两次绘制事件。(print "Event occurred"在事件处理程序中写一行,看看这个方法被调用了多少次。)调整窗口大小,失去或获得焦点,最小化或最大化窗口,所有这些都会导致绘制事件被触发。

于 2013-10-06T12:17:47.093 回答
1

app.exec_()启动 qt 主循环,当每个创建的小部件被销毁时结束(例如通过关闭它的窗口)。该paintEvent函数是一种方法,您可以从QWidget子类(如给定Example类)重载,当 QT 显示、更新或重绘 Widget 时会调用该方法。

您可以在Qt 文档PyQt 文档中查找这些内容(这主要是 QT 文档的不同格式的副本,但有时包含一些有关 PyQt 特定内容的有价值信息)。

于 2012-08-03T10:13:26.507 回答