前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PySide6 GUI 编程(3):信号槽机制

PySide6 GUI 编程(3):信号槽机制

原创
作者头像
bowenerchen
修改2024-05-19 19:56:39
1230
修改2024-05-19 19:56:39
举报
文章被收录于专栏:编码视界编码视界

信号与槽的内在逻辑

信号与槽的逻辑关联
信号与槽的逻辑关联

信号与槽:

  • 松耦合,发送者不需要关注接收者的接口信息
  • 接收者执行动作是异步的
  • 执行动作的整体效率比回调函数要低

回调函数:

  • 强耦合,调用者和被调用者必须遵守回调接口规范(如:接口参数规范)
  • 执行回调函数是同步的
  • 执行动作的整体效率比信号槽要高

以 QPushButton 按钮点击为例

点击按钮的状态拆解
点击按钮的状态拆解

当我们点击按钮时,手指要指定的步骤是:按下按钮 --> 释放按钮

按钮对应会产生三种状态:

  • 按钮被按下
  • 按钮被释放
  • 按钮完成了一次点击 其中最后一个状态,是在按下和释放两者都完成之后才会产生的

对应的代码我们这样来模拟:

代码语言:python
复制
import time

from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('My Signal&Slot Window 我的信号与槽窗口')
        button = QPushButton('My Push Button 我的按钮')
        button.setCheckable(True)
        button.clicked.connect(self.the_button_was_clicked)
        button.pressed.connect(self.the_button_was_pressed)
        button.released.connect(self.the_button_was_released)
        self.setCentralWidget(button)

    def the_button_was_clicked(self):
        print(self.windowTitle(), time.time(), time.strftime('%Y-%m-%d %H:%M:%S'), "Button Clicked")

    def the_button_was_pressed(self):
        print(self.windowTitle(), time.time(), time.strftime('%Y-%m-%d %H:%M:%S'), "Button Pressed")

    def the_button_was_released(self):
        print(self.windowTitle(), time.time(), time.strftime('%Y-%m-%d %H:%M:%S'), "Button Released")


if __name__ == '__main__':
    app = QApplication([])
    window = MyWindow()
    window.show()

    app.exec()
点击按钮时信号与动作的映射
点击按钮时信号与动作的映射
运行效果
运行效果
  • 当按下按钮后在原地释放按钮,则会打印红框中出现的内容,这是因为确实完成了一次点击;
  • 当按下按钮后手指拖动按钮到按钮外的其他区域,则会出现绿框中出现的内容,因为这个时候并不是在完成点击,而是按下后尝试拖动按钮。

自定义信号与槽

代码语言:python
复制
from PySide6.QtCore import QObject, Signal


class Emitter(QObject):
    my_signal_0 = Signal()
    my_signal_1 = Signal(str)  # 创建一个带有1个参数的信号
    my_signal_2 = Signal(str, str)  # 创建一个带有2个参数的信号

    def emit_signal_0(self):
        print('emit_signal_0 Send Signal, No Parameters')
        self.my_signal_0.emit()  # 发射信号

    def emit_signal_1(self, a):
        print('emit_signal_1 Send Signal, Parameters:', a)
        self.my_signal_1.emit(a)  # 发射信号并传递1个参数

    def emit_signal_2(self, a, b):
        print('emit_signal_2 Send Signal, Parameters:', a, b)
        self.my_signal_2.emit(a, b)  # 发射信号并传递2个参数


class Receiver(QObject):

    def slot_function_0(self):
        print(self.objectName(), "slot_function_0 Received")

    def slot_function_1(self, x):  # 槽函数接受1个参数
        print(self.objectName(), "slot_function_1 Received:", x)

    def slot_function_2(self, x, y):  # 槽函数接受2个参数
        print(self.objectName(), "slot_function_2 Received:", x, y)


if __name__ == '__main__':
    # 发送者
    emitter = Emitter()
    emitter.setObjectName('TestEmitterObj')

    # 接收者
    receiver = Receiver()
    receiver.setObjectName('TestReceiverObj')

    # 连接信号与槽函数
    emitter.my_signal_0.connect(receiver.slot_function_0)
    emitter.my_signal_1.connect(receiver.slot_function_1)
    emitter.my_signal_2.connect(receiver.slot_function_2)

    # 发射信号
    emitter.emit_signal_0()

    emitter.emit_signal_1('one')

    emitter.emit_signal_2('one', 'two')

信号与参数个数需要匹配

信号与参数个数
信号与参数个数
运行效果
运行效果

信号与参数个数不匹配时的异常

当信号发送时参数个数不匹配时会抛出错误:

emitter.emit_signal_1('one', 'two')

参数不匹配时的抛出异常
参数不匹配时的抛出异常

信号的重载

信号的重载在 PySide6 中并不推荐使用,对于从 QT5 遗留的代码可以继续使用这一能力。

信号重载
信号重载

示例代码:

代码语言:python
复制
import sys

from PySide6.QtCore import QObject, Signal, Slot
from PySide6.QtWidgets import QApplication


class Communicate(QObject):
    # create two new signals on the fly: one will handle
    # int type, the other will handle strings
    speak = Signal((int,), (str,))

    def __init__(self, parent = None):
        super().__init__(parent)

        self.speak[int].connect(self.say_something)
        self.speak[str].connect(self.say_something)

    # define a new slot that receives a C 'int' or a 'str'
    # and has 'say_something' as its name
    @Slot(int)
    @Slot(str)
    def say_something(self, arg):
        if isinstance(arg, int):
            print("This is a number:", arg)
        elif isinstance(arg, str):
            print("This is a string:", arg)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    someone = Communicate()

    # emit 'speak' signal with different arguments.
    # we have to specify the str as int is the default
    someone.speak.emit(10)
    someone.speak[str].emit("Hello everybody!")
运行效果
运行效果

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 信号与槽的内在逻辑
  • 以 QPushButton 按钮点击为例
  • 自定义信号与槽
    • 信号与参数个数需要匹配
      • 信号与参数个数不匹配时的异常
      • 信号的重载
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档