Qt for python 的信号槽机制使用

Posted Fu_Lin_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt for python 的信号槽机制使用相关的知识,希望对你有一定的参考价值。

前言

我看了网上的很多信号槽的使用,但是没有一个系统性的,而且好像很多方法都已经不能用了,网上很多信号的发送方式感觉都用不了了,方法就不存在,所以在这篇教程中,将会讲解如何用 Qt for Python 处理自定义的信号和槽。信号和槽是Qt的一个特色,用来让你的图形组件与其他图形组件或 Python 代码交流。在例程中,我们创建一个自定义的py文件,继承于QObject, 然后自己实现信号,外面调用方法,关联自定义的信号和对应槽函数,下面看代码!

自定义信号槽实现

首先新建一个TestSignalAndSlot.py文件, 看我的定义,很简单,就自定义2个信号,重点讲解的自定义的无参信号和有参信号的发射

class TestSignalAndSlot(QObject):

    msg_state_change = Signal(None)  #定义无参数信号
    msg_str_change =Signal(str) #定义QString类型的有参数信号


    def sendMsg(self):
        self.msg_state_change.emit(None)

    def sendStrMsg(self, msg):
        self.msg_str_change.emit(msg)

说明一下,如果信号无参数,可以直接设置为空也就是None, 或者不设置也行,最好是设置一下,发送信号的方式这里说明一下,必须要调用emit(), 重点就是这个方法你打点调用,它不会自动补全出来,而去你自己去找还找不到,就是这么奇葩,还会提示没有此方法,如下图:

看到我的图,没有参数时,可以直接调用emit()或者emit(None) 都行, 如果这样发送信号,如下:

    def sendMsg(self):
        self.msg_state_change()

将会报错native Qt signal is not callable, 如下:

File "D:\\QtTestPro\\python_qml_test\\TestSignalAndSlot.py", line 12, in sendMsg
    self.msg_state_change()
TypeError: native Qt signal is not callable

下面看调用方main.py, 代码如下:

def on_msg_state_slot():
    print("响应了无参数信号")

def on_msg_str_slot(msg):
    print("响应字符消息:", msg);
    
if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)

    testSignal = TestSignalAndSlot()
    testSignal.msg_state_change.connect(on_msg_state_slot)
    testSignal.msg_str_change.connect(on_msg_str_slot)
	
	# 呼叫无参信号发射
    testSignal.sendMsg()
    sys.exit(app.exec_())

我们需要将测试信号msg_state_change与定义的 on_msg_state_slot() 函数连接。信号槽的连接方式有新老两种方法可以建立连接,我这里实现的就是新的方法。TestSignalAndSlot 类预定义了一个叫 msg_state_change 的信号,每当调用sendMsg() 方法就会触发该信号。我们要把这个信号和 on_msg_state_slot() 函数连接:

testSignal.msg_state_change.connect(on_msg_state_slot)

msg_str_change信号的连接同上,就不累赘了,下面看运行main.py后的终端打印结果:

可以看到,界面运行起来了,槽函数接收到了,信号也触发了,这是无参信号的触发显示,下面看看有参数信号的触发结果,我们将main.py中的testSignal.sendMsg()方法改成testSignal.sendStrMsg(),看代码如下:

def on_msg_str_slot(msg):
    print("响应字符消息:", msg);

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
    if not engine.rootObjects():
        sys.exit(-1)

    testSignal = TestSignalAndSlot()
    testSignal.msg_state_change.connect(on_msg_state_slot)
    testSignal.msg_str_change.connect(on_msg_str_slot)
    
	# 呼叫有参信号发射
    testSignal.sendStrMsg("测试 Qt for python 有参数信号槽连接是否打通")
    sys.exit(app.exec_())

此时运行将会触发on_msg_str_slot 方法,运行终端如下:

界面运行出来,终端也打印了on_msg_str_slot方法接收到的消息, 至此自定义的信号和槽就算是入门了,会了自定义的信号和槽连接发射,Qt自带的那就简单的不得了 ! 可以自己依葫芦画瓢测试下,这里就不多说了。

下面我提一下老版本方式的信号槽连接方式,更改main.py 的信号槽部分如下:

老版本方式依旧采用了SIGNAL ()和SLOT()宏

    # 老的传统信号槽连接方式
    # 可用
    QObject.connect(testSignal, SIGNAL("msg_state_change()"), on_msg_state_slot);
    # 不可用
    #QObject.connect(testSignal, SIGNAL('msg_str_change(str)'), on_msg_str_slot)

发现不带参数的使用这种情况可以使用,带参数的不行,调用没反应,翻了全网发现使用这种方式的都是用的无参数形式的,其他的都没介绍,官方文档也介绍的不全,我猜想可能槽需要对象并使用SLOT宏吧,不过我也没深究了,毕竟现在都是用的新方式,所以不必纠结此方法了!

以上是关于Qt for python 的信号槽机制使用的主要内容,如果未能解决你的问题,请参考以下文章

QT的信号槽机制

Qt的信号槽机制可以保障线程安全吗

非Qt工程使用Qt的信号槽机制

qt信号和槽机制的问题

Qt编程中信号与槽机制可以用啥方法替换

Qt高级——Qt信号槽机制源码解析