PyQt5 是 Python 语言的一种 GUI 编程框架,它提供了丰富的 GUI 组件和工具,还提供了一种名为信号(Signals)与插槽(Slots)的机制,用于实现组件之间的通信。本文将详细讲解 PyQt5 信号和插槽的使用攻略,帮助初学者快速上手。
1. 理解 PyQt5 信号和插槽
PyQt5 中的信号和插槽机制主要用于组件之间的相互通信,它基于观察者模式(Observer Pattern),即信号发射方(Sender)发射信号,信号接收方(Receiver)接收信号,并采取相应的操作。基本流程如下:
- 用户操作界面,例如点击按钮或输入文本等,会导致相应的信号被发射(emit);
- 信号被发射后,接收方会捕获(catch)这个信号,执行相应的插槽函数(Slot);
- 在插槽函数中,可以根据需要进行相应的操作。
信号和插槽是通过 QObject 对象来实现的,因此几乎所有的 PyQt5 组件都支持信号和插槽机制。
2. PyQt5 信号和插槽的使用方法
2.1 定义信号和插槽
在 PyQt5 中,可以通过 pyqtSignal()
方法和 @pyqtSlot()
装饰器来定义信号和插槽。
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
class Sender(QObject):
# 定义信号
signal = pyqtSignal()
class Receiver(QObject):
@pyqtSlot()
# 定义插槽
def slot(self):
print('Receive Signal')
在上面的例子中,Sender
类中定义了一个名为 signal
的信号,通过 pyqtSignal()
方法进行定义,无需参数。类 Receiver
中定义了一个名为 slot
的插槽,通过 @pyqtSlot()
装饰器进行定义,无需参数。
2.2 连接信号和插槽
在 PyQt5 中,可以通过 connect()
方法将信号和插槽连接起来,如下所示:
sender = Sender()
receiver = Receiver()
sender.signal.connect(receiver.slot)
上述代码将 Sender
类的 signal
信号和 Receiver
类的 slot
插槽进行了连接,当 Sender
类发射信号时,Receiver
类的插槽函数将被调用。
2.3 发射信号
在 PyQt5 中,可以通过 emit()
方法来发射信号,例如:
sender.signal.emit()
上述代码将发射 Sender
类定义的 signal
信号,将会触发 Receiver
类中定义的 slot
插槽的执行。
3. PyQt5 信号和插槽的应用示例
3.1 点击按钮更新文本框
下面是一个简单的示例,当用户点击按钮时,更新文本框的内容:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QVBoxLayout
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.button = QPushButton('Click me', self)
self.button.clicked.connect(self.updateText)
self.edit = QLineEdit(self)
vbox = QVBoxLayout()
vbox.addWidget(self.button)
vbox.addWidget(self.edit)
self.setLayout(vbox)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
def updateText(self):
self.edit.setText('Hello World')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在上述示例中,当用户点击按钮时,会调用 updateText
插槽函数,将文本框的内容设置为 Hello World
。
3.2 拖拽放置实现图片预览
下面是另一个示例,用户可以通过拖拽放置图片文件来实现图片预览。当用户在窗口上拖拽图片文件时,会将图片显示在窗口中。
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow
from PyQt5.QtGui import QPixmap
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
self.label = QLabel(self)
self.setCentralWidget(self.label)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Drag & Drop')
self.show()
def dragEnterEvent(self, e):
if e.mimeData().hasImage:
e.accept()
else:
e.ignore()
def dropEvent(self, e):
if e.mimeData().hasImage:
filename = e.mimeData().urls()[0].toLocalFile()
pixmap = QPixmap(filename)
self.label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
self.setWindowTitle(filename)
e.accept()
else:
e.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在上述示例中,当用户将图片文件拖拽到窗口上时,会触发 dragEnterEvent
插槽函数和 dropEvent
插槽函数,用于接收和处理拖拽事件,并在窗口中显示拖拽的图片。