如果用户界面没有互动性,那么它有什么用呢?这一章主要是学习如何使用widget来制作响应式的用户界面,对用户的交互作出反应,处理不同的事件,并将重要的信息反馈给用户。我们将看一下几个常见的部件,看看如何使用它们来设计和建立GUI应用程序。
在进入任何代码之前,让我们先了解一下PyQt的事件处理。
GUI是事件驱动的,这意味着它们响应由用户创建的事件,这些事件来自键盘或鼠标,或由系统引起的事件,如计时器或连接到蓝牙时。在Qt中,特殊类型的事件甚至被生成以处理部件之间的通信。无论它们是如何产生的,应用程序都需要监听这些事件,并对它们做出适当的响应。这就是所谓的事件处理。当exec()被调用时,应用程序开始监听事件,直到程序被关闭。
在PyQt中,事件处理有两种方式,一种是通过事件处理程序,一种是通过信号和槽来处理。事件处理程序负责事件的处理。有不同类型的事件可以被处理,例如paintEvent()用于重新绘制一个widget的外观,或者keyPressEvent()用于处理按键。在Qt中,事件是由QEvent类创建的对象。
Qt中对象之间的通信,如widget,是由信号和槽来处理的。每当一个事件发生时就会产生信号,例如当一个按钮被点击或一个复选框被打开或关闭。然后,这些信号需要以某种方式进行处理。槽是连接到一个事件的方法,并在响应信号时执行。槽可以是内置的PyQt函数或你自己创建的Python函数。
每个PyQt类都有自己的各种信号,其中许多信号是从父类中继承的。让我们看一个例子。每当用户点击窗口中的一个按钮,这个按钮的点击就会发出,或者说发射一个信号:button.clicked.connect(self.buttonClicked)
这里,button是一个widget,clicked是信号。为了利用这个信号,我们必须使用connect()来调用一些函数,在这里是buttonClicked(),它是槽。然后,buttonClicked()方法可以执行一些动作,比如打开一个新窗口。许多信号还向槽传递额外的信息,比如一个布尔值,告诉我们按钮是否被按下。
QPushButton小组件可以被用来执行动作和做出选择。当你点击QPushButton小组件时,它会发出一个可以连接到一个函数的信号。虽然你可能通常会遇到带有文字的按钮,如OK、Next、Cancel、Close、Yes或No,但你也可以用描述性的文字或图标创建你自己的按钮。
# buttons.py
# Import necessary modules
import sys
from PyQt6.QtWidgets import (QApplication, QWidget, QLabel, QPushButton)
from PyQt6.QtCore import Qt
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initializeUI()
def initializeUI(self):
"""Set up the application's GUI."""
self.setGeometry(100, 100, 250, 250)
self.setWindowTitle("QPushButton Example")
self.setUpMainWindow()
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
def setUpMainWindow(self):
"""Create and arrange the widgets in the main window."""
self.times_pressed = 0
self.name_label = QLabel("Don't push the button!", self)
self.name_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.name_label.move(60, 30)
self.button = QPushButton("Push Me", self)
self.button.move(80, 70)
self.button.clicked.connect(self.buttonClicked)
变量times_pressed将被用来记录按钮被按下的次数。这个应用程序的窗口只包含一个QLabel和一个QPushButton。 与其使用setText()来分配name_label的文本,我们不如在实例化QLabel对象时将我们想要显示的文本作为第一个参数传递。
有可能对显示文本的部件的内容进行对齐。要做到这一点,请使用setAlignment(),由于我们使用的是PyQt6,请确保传递完整的枚举类型:Qt.AlignmentFlag。
这里,让我们使用AlignCenter,它是AlignVCenter和AlignHCenter的组合。使用move()来设置小组件的绝对位置。
接下来,创建QPushButton对象,并将按钮的文本和self(对MainWindow类的引用)作为参数传给它。点击按钮将发出点击信号,该信号与buttonClicked()槽相连。
def buttonClicked(self):
"""Handle when the button is clicked.
Demonstrates how to change text for widgets,
update their sizes and locations, and how to
close the window due to events.
"""
self.times_pressed += 1
if self.times_pressed == 1:
self.name_label.setText("Why'd you press me?")
if self.times_pressed == 2:
self.name_label.setText("I'm warning you!")
self.button.setText("Feelin' lucky?")
self.button.adjustSize()
self.button.move(70, 70)
if self.times_pressed == 3:
print("The window has been closed!")
self.close()
# buttons.py
# Import necessary modules
import sys
from PyQt6.QtWidgets import (QApplication, QWidget, QLabel, QPushButton)
from PyQt6.QtCore import Qt
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initializeUI()
def buttonClicked(self):
"""Handle when the button is clicked.
Demonstrates how to change text for widgets,
update their sizes and locations, and how to
close the window due to events.
"""
self.times_pressed += 1
if self.times_pressed == 1:
self.name_label.setText("Why'd you press me?")
if self.times_pressed == 2:
self.name_label.setText("I'm warning you!")
self.button.setText("Feelin' lucky?")
self.button.adjustSize()
self.button.move(70, 70)
if self.times_pressed == 3:
print("The window has been closed!")
self.close()
def setUpMainWindow(self):
"""Create and arrange the widgets in the main window."""
self.times_pressed = 0
self.name_label = QLabel("Don't push the button!", self)
self.name_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.name_label.move(60, 30)
self.button = QPushButton("Push Me", self)
self.button.move(80, 70)
self.button.clicked.connect(self.buttonClicked)
def initializeUI(self):
"""Set up the application's GUI."""
self.setGeometry(100, 100, 250, 250)
self.setWindowTitle("QPushButton Example")
self.setUpMainWindow()
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())