PyQt5 信号和插槽

  • Post category:Python

PyQt5 是 Python 语言的一种 GUI 编程框架,它提供了丰富的 GUI 组件和工具,还提供了一种名为信号(Signals)与插槽(Slots)的机制,用于实现组件之间的通信。本文将详细讲解 PyQt5 信号和插槽的使用攻略,帮助初学者快速上手。

1. 理解 PyQt5 信号和插槽

PyQt5 中的信号和插槽机制主要用于组件之间的相互通信,它基于观察者模式(Observer Pattern),即信号发射方(Sender)发射信号,信号接收方(Receiver)接收信号,并采取相应的操作。基本流程如下:

  1. 用户操作界面,例如点击按钮或输入文本等,会导致相应的信号被发射(emit);
  2. 信号被发射后,接收方会捕获(catch)这个信号,执行相应的插槽函数(Slot);
  3. 在插槽函数中,可以根据需要进行相应的操作。

信号和插槽是通过 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 插槽函数,用于接收和处理拖拽事件,并在窗口中显示拖拽的图片。