应用特点
- 控制台启动
- 没有装饰栏
- 没有标题栏
- 没有系统菜单
- 没有关闭按钮
运行效果
启动后,程序会在后台默默运行,仅是简单地记录时间直到达到给定的时间。此时,程序会弹出一个文本消息窗口。大约窗口显示后一分钟,程序会自动终止。
源代码
# encoding:utf-8
import sys
import time
from PyQt4 import QtCore
from PyQt4 import QtGui
# sys.argv用于访问命令行参数
app = QtGui.QApplication(sys.argv)
# handle the argv
try:
due = QtCore.QTime.currentTime()
message = 'Alert!'
if len(sys.argv) < 2:
raise ValueError
hours, mins = sys.argv[1].split(':')
due = QtCore.QTime(int(hours), int(mins))
if not due.isValid():
raise ValueError
if len(sys.argv) > 2:
message = ' '.join(sys.argv[2:])
except ValueError:
# 24hr clock
message = 'Usage: alarm_clock.py HH:MM [optional message]'
while QtCore.QTime.currentTime() < due:
# 20 seconds
time.sleep(20)
label = QtGui.QLabel('<font color=red size=72><b>' + message + '</b></font>')
label.setWindowFlags(QtCore.Qt.SplashScreen)
label.show()
# 1 minute
QtCore.QTimer.singleShot(60000, app.quit)
app.exec_()
解析
import sys
import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
导入sys
模块,是因为我们想访问包含在sys.argv
列表中的那些命令行参数,导入·模块,则是因为我们需要它的sleep()
函数;而导人这两个PyQt
模块,则是因为需要使用 GUI
和 QTime
类。
# sys.argv用于访问命令行参数
app = QtGui.QApplication(sys.argv)
先从创建QApplication
对象开始。每个PyQt GUI
应用程序都必须有一个QApplication
对象。这个对象会提供访问全局信息的能力,如应用程序的目录、屏幕大小(以及对于多线程 系统来说,这个应用程序是在哪个屏上)等。这个对象还会提供稍后要讨论的事件循环。
在创建QApplication
对象时,给它传递了命令行参数;这是因为,PyQt
可以识别一些 自己的参数,如-geometry
和-style
,所以需要给一个让它读到这些参数的机会。如果 QApplication
能够识别任意一个参数,它就会对它们进行一些操作,并将其从给定的参数 列表中移除掉。QApplication
能够识别的那些参数列示在QApplication
的初始化文档中。
当程序中存在上述语句时,会报错如下:
QWidget: Must construct a QApplication before a QPaintDevice
参数处理:
# handle the argv
try:
due = QtCore.QTime.currentTime()
message = 'Alert!'
if len(sys.argv) < 2:
raise ValueError
hours, mins = sys.argv[1].split(':')
due = QtCore.QTime(int(hours), int(mins))
if not due.isValid():
raise ValueError
if len(sys.argv) > 2:
message = ' '.join(sys.argv[2:])
except ValueError:
# 24hr clock
message = 'Usage: alarm_clock.py HH:MM [optional message]'
在比较靠后的地方,这个程序需要一个时间点,所以把due
变量值设定为现在的时间。我们 还提供了一个默认消息。如果用户没有给定哪怕至少一个的命令行参数值(时间),就会抛出 (raise
)一个ValueError
异常。这样就会显示一个当前时间,并且会给出含有“用法”错误的消息
如果第一个参数不含冒号,那么在尝试调用split
将两个元素解包时,就将触发一个ValueError
的异常。如果小时数和分钟数不是有效的数字,那么int()
将会触发一个ValueError
异常; 而如果小时数和分钟数超限,导致成了无效的QTime
, 那么就需要自 己来触 发一个ValueError
异常。尽管Python提供了自己的date
和time
类,但PyQt
的date
和time
类通常会显得更为方便些,所以推荐使用PyQt
的这些类。
如果该time
有效,那么就把这条消息与其他命令行参数(如果还有的话)用空格分隔开; 如果没有其他参数,就用开头设置的默认信息“Alert
!”来代替之(当一个程序是用命令行方式 启动时,会给定一系列的参数,第一个称为调用名,而剩下的其他非空字符,也就是输人命令 行中的其他每个单词,都称为字符序列。这些字符序列或许会被shell
改变,例如,可能会用 通配符进行匹配。Python
自己的字符序列位于sys.argv
列表中)。
while QtCore.QTime.currentTime() < due:
# 20 seconds
time.sleep(20)
把当前时间和目标时间连续不断地进行循环比较。如果当前时间超过了目标时间,循环就会停止。原本是可以在循环体内放一个pass
声明(statement
)的,但如果是这样的话,Python
就 会非常快地一遍遍执行这个循环,而过多地占用处理器可不是什么好现象,time.sleep()
命令会让Python
暂停处理一段时间后再继续处理,这里暂停的时间是20
秒。这样就可以让机器上的其他程序也能够得到更多的运行机会,因为我们也不想在等这个程序到达截止时间的期间什么也不做。暂且先不提创建QApplication
对象,目前所做的仅仅就是标准的控制台程序设计工作。
label = QtGui.QLabel('<font color=red size=72><b>' + message + '</b></font>')
label.setWindowFlags(QtCore.Qt.SplashScreen)
label.show()
# 1 minute
QtCore.QTimer.singleShot(60000, app.quit)
app.exec_()
在创建了 QApplication
对象后,就会显示一条消息,因为截止时间已到,所以现在就可以 创建程序了。一个GUI程序需要一些窗口部件,这样就需要用有一个标签(labe
)来显示该消 息。QLabel
可以接收HTML
文本,所以就给它一个HTML
字符串,让它能够将这段消息显示 为加黑、红色、大小为72点素(point
)①。
在PyQt
中,任何窗口部件都可以作为顶级窗口,即使是按钮和标签都行。当窗口部件这么用的时候,PyQt
就会自动给它加一个标题栏。在这个应用程序中,并不想要一个标题栏,所 以要把该标签的各个窗口标记(flag
)均设置为闪屏(splash screen
)模式,因为这种模式不会有标题栏了。一旦把要作为窗口的标签设置完毕,就可以对其调用show()
函数了。此时,该标 签窗口却没有显示出来show ()
的调用仅仅是计划执行一个“重绘事件”(paim event
),也就 是说,show ()
会向QApplication
对象的事件队列中添加一个新的事件,以请求对特定的窗口部件进行绘制。
接下来,会设置一个单次定时器(single-shot timer
)。这是因为Python
库的time.sleep
函数使用的时间是秒,而QTiraer.singleShot()
函数使用的是毫秒。给singleShot()
方法 两个参数:让这个时间需要持续多长(这里是1分钟),时间到期后调用哪个函数或者方法。
用PyQt
的术语来说,上述给出的方法或者函数叫做“槽"(slot),尽管在PyQt
的文档中,也会用术语“可调用”(callable
)、“ Python 槽
”(Python slot
)和“Qt
”槽(Qt slot
)来区分 Python
的 _slots_
,这是在Python
语言指南(Python Language Reference
)中给出的一个新特性类。所以现在要计划执行两个事件:一个是需要立即执行的绘制(paint
)事件,一个是需要在一分钟后执行的定时器(timer
)超时事件。
调用app.exec_()
会开始执行QApplication
对象的事件循环①。第一个事件就是绘制事件,所以标签窗口会带着给定的消息显示在屏幕上。大约一分钟之后,会发生定时器的超时 事件,此时会调用QApplication.quit
方法。这个方法会干净地结束掉该GUI
应用程序。 它会关闭所有已打开的窗口,释放所有占用的资源,然后退出程序。