本节将使您了解在一个部件上的事件如何调用执行关联部件上的预定义操作。因为,我们想通过单击按钮从一个 Line Edit 部件上复制内容,当在按钮上发生了 pressed() 事件时,我们需要调用 selectAll() 方法。同样,在按钮上发生 released() 事件时,我们需要调用 copy() 方法。在单击另一个按钮时,将剪贴板上的内容粘贴到另一个 Line Edit 部件中,当在另一个按钮上发生 clicked() 事件时,我们需要调用 paste() 方法。
让我们创建一个包括两个 Line Edit 和 两个 Push Button 部件的应用程序。单击第一个按钮,第一个 Line Edit 部件中的文本将会被复制,在单击第二个按钮时,将第一个 Line Edit 部件中的复制内容粘贴到第二个 Line Edit 部件中。
让我们基于 Dialog without Buttons 模板新建一个应用程序,步骤如下:
首先,通过拖动 Widget 框中的 Line Edit和 Push Button部件并放在窗体中,这样就向窗体中添加了QLineEdit和QPushButton。
为了在编辑时能够预览窗体,可以使用Form、Preview或使用Ctrl+R。
当用户选择窗体上的按钮时,为了复制 Line Edit 部件中的文本,你需要将按钮的信号与 Line Edit的槽进行连接。让我们学习如何去做。
一开始,窗体是处在部件编辑模式,如果要使用信号和槽的连接,你先要切换到信号和槽的编辑模式:
选择工具栏上的 Edit Signals/Slots 图标进入信号和槽的编辑模式。
在窗体上,选择这个按钮,将鼠标拖动到 Line Edit 部件,并释放鼠标按键。弹出 Configure Connection 对话框,并允许你在Push Buton 和 Line Edit 部件之间建立信号和槽的连接,如下截图所示:
与 Line Edit 连接的 Push Button的信号将会以箭头的形式显示,代表这两个部件之间的信号与槽已经连接了,如下面的截图所示:
将 Push Button 部件的 text 属性设置为Copy,实际表示将会复制 Line Edit 部件中输入的文本。
接下来,我们将重复这个过程,单击按钮并将鼠标拖动到 Line Edit 部件,以将按钮的 released() 信号与 Line Edit 部件的 copy() 槽进行连接。在窗体上,你可以看到另一个箭头,代表了在这两个部件中建立了每个信号和槽的连接,如下截图所示:
为了粘贴复制过的内容,拖动一个按钮和一个 Line Edit 部件并放到窗体上。
将 Push Button 部件的 text 属性设置为 Paste。
单击按钮,并保持鼠标左键处于按下状态,拖动并在 Line Edit 部件上释放。
在 Configure Connection 对话框中,pushButton(QPushButton) 列中选择 clicked() 事件,并在 lineEdit(QLineEdit)列中选择 paste() 槽。
将窗体保存为 demoSignal1.ui。现在窗体显示如下截图所示:
窗体将保存为以 .ui 后缀的文件。这个 demoSignal1.ui 文件包含了窗体的所有信息,包括其中的部件,布局等等。这个 .ui 文件是一个XML文件,并且它需要使用 pyuic5 工具转换成 Python 代码。生成的 Python代码文件为 demoSignal1.py,可以在本书附带源码文件中看到。在 demoSignal1.py 文件中 ,你会发现它导入了QtCore和QtGui这两个模块中的所有东西,因为你在开发GUI应用时需要使用它们:
QtCore:QtCore模板组成了所有基于Qt应用的基础。它包含了大部分基础类,如QCoreApplication,QObject等等。这些类会处理重要的任务,如事件处理,信号和槽的实现机制,I/O操作,处理字符串等等。这个模块还包含了一些类,包括QFile,QDir,QIODevice,QString,QDate和Qtime。
QtGui:顾名思义,这个QtGui模块包含了那些跨平台GUI应用所需要的类。这个模块包含了一些GUI类,如QCheckBox,QComboBox,QDateTimeEdit,QLineEdit,QPushButton,QPainter,QPaintDevice,QApplication,QTextEdit和QTextDocument。
将demoSignalSlot1.py文件作为头文件导入到你将要调用其用户界面设计的程序中。
创建另外一个名为 calldemoSignal1.pyw文件 并导入 demoSignal1.py文件:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from demoSignalSlot1 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.show()
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
这个sys模块的导入是用来访问命令行参数并将其存入到sys.argv的列表中。这是因为每一个PyQt GUI应用程序都必须有一个QApplication对象来提供访问诸与应用程序路径,屏幕大小等等一些信息,因此,你需要创建一个QApplication对象。当创建一个QApplication对象时,为了让PyQt能够使用并应用命令行参数(如果有的话),你需要将命令行参数传入。你创建了一个MyForm实例并调用它的 show() 方法,这个方法会将一个新的事件添加到QApplication的事件队列中。这个新事件是用来显示MyForm类中指定的所有部件。这个app.exec_()方法的调用是用于启动QApplication对象的事件循环。一旦事件循环开启时,就会显示MyForm类中的顶层部件窗口,和它的子部件。所有的系统生成事件,和用户交互事件都会添加到这个事件队列中。这个应用程序事件循环继续检查并查看是否发生了一个事件。当一个事件发生时,事件循环就会处理它并设置与之相关联的槽或方法。在关闭应用程序的顶层部件时,PyQt会删除这个部件并执行应用程序关闭时的清理工作。
在PyQt中,任何部件都可以用来作为一个顶层窗口。这个super.__init__()方法调用了MyForm基类的构造方法,也就是说,从MyForm类中调用了QDialog的构造方法,表明了,通过这个类显示的QDialog是一个顶层窗口。
用户界面设计是通过在Python代码(UI_Dialog)中创建的类中的setupUI()方法初始化的。我们创建一个UI_Dialog类的实例,这个类由Python代码创建,并由setupUI()方法调用。这个Dialog将创建为所有用户部件的父部件并显示在屏幕上。记住,QDialog,QMainWindow和所有PyQt部件都继承自QWidget。
运行应用程序,你将得到两对Line Edit和Push Button部件。在一个Line Edit部件中输入文本,当你单击Copy按钮时,这个文本会被复制。
现在,单击Paste按钮,复制的文本将会被粘贴到每二个Line Edit部件中,如下截图所示: