PyQt5 一信号多槽 [英] PyQt5 one signal and multiple slots

查看:118
本文介绍了PyQt5 一信号多槽的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面提出了一个简单的信号/槽机制.当通过 QSlider::valueChanged() 更改值时,QSlider 会调用该信号.并且插槽通过 QLCDNumber::display() 方法调用.

令我困惑的是,为什么 PyQt5 的文档很少,而大多数文档都指向 Qt5 的链接.我对代码的具体问题是:

1) 如果 QSlider::valueChanged()(信号)需要一个整数作为参数为什么我们只传入 QLCDNumber::display() (slot) 这是一个空函数.因此不会传入任何内容.

2) 在下面注释掉的代码中,我无法调用第二个插槽.您可以为 1 个信号调用的插槽数量有限制吗?如果有我如何在 PyQt5 中调用多个插槽.

我相信因为 printLabel() 不是定义的插槽,这就是我遇到问题的原因.我可以在 ::connect() 参数中包含任意数量的插槽吗?或者我是在以一种骇人听闻的方式处理这个问题.

导入系统从 PyQt5.QtCore 导入(Qt)从 PyQt5.QtWidgets 导入(QWidget、QLCDNumber、QSlider、QVBoxLayout、QApplication)类示例(QWidget):def __init__(self):super().__init__()self.initUI()def printLabel(self, str):打印(字符串)定义 initUI(self):lcd = QLCDNumber(self)sld = QSlider(Qt.Horizo​​ntal, self)vbox = QVBoxLayout()vbox.addWidget(lcd)vbox.addWidget(sld)self.setLayout(vbox)#这条线有效sld.valueChanged.connect(lcd.display)#这行不行#sld.valueChanged.connect(lcd.display, self.printLabel("hi"))self.setGeometry(300, 300, 250, 150)self.setWindowTitle('信号和槽')自我展示()如果 __name__ == '__main__':app = QApplication(sys.argv)ex = 示例()sys.exit(app.exec_())

解决方案

整理你的观点:

  • Qt5 文档至少包含您需要了解的 90% 的内容,因此在 PyQt5 文档中重复所有内容几乎没有意义,而是主要集中在 PyQt 特定的功能上(请参阅 <例如,href="http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html" rel="noreferrer">信号和插槽 文章).Qt5 是一个 C++ 库.您无需了解 C++ 即可使用 PyQt(或阅读 Qt 的优秀文档),但您几乎不能指望完全避免使用它.

  • QSlider.valueChanged 信号发送一个 int 值到所有连接到它的插槽.QLCDNUMer.display接收一个字符串、整数或浮点对象(即它有三个重载).对于内置的 Qt 插槽,必须有一个与信号发送的内容相匹配的重载.但是 PyQt 中用户定义的槽可以是 any python 可调用对象,并且签名不匹配也没有关系(任何额外的参数都会被丢弃).话虽如此,可以使用 pyqtSlot 装饰器(因此允许在 PyQt 中指定多个重载)为用户定义的槽定义显式签名.>

  • 如上面提到的 PyQt 文章的第一部分所述,信号和槽都可以有多个连接.文章还详细介绍了 PyQt 特定的 API(包括 pyqtSlot),并给出了如何使用它们的示例.

以下是如何连接到多个插槽的示例:

类示例(QWidget):...定义 initUI(self):...#连接到内置插槽sld.valueChanged.connect(lcd.display)#连接到用户定义的手数sld.valueChanged.connect(self.printLabel)#任何可调用的python都可以sld.valueChanged.connect(lambda x: print('lambda:', x))...def printLabel(self, value):打印('打印标签:',值)

I have come up with a simple signal/slot mechanism below. The signal is called by QSlider when the value is changed via QSlider::valueChanged(). And the slot is called via the QLCDNumber::display() method.

What is confusing to me is why PyQt5 has so little documentation and most documentation leads to links for Qt5. The specific issue I have with the code is:

1) If QSlider::valueChanged() (signal) expects an integer as a parameter why do we only pass in QLCDNumber::display() (slot) which is a void function. Therefore nothing is going to be passed in.

2) In the commented-out code below, I am not able to call a second slot. Is there a limit to the number of slots you can call for 1 signal? If there is how do I go about calling multiple slots in PyQt5.

Edit: I believe because printLabel() is not a defined slot, this is why I am getting issues. Is it possible for me to include any amount of slots in the ::connect() parameters? Or am I approaching this in a hacky way.

import sys
from PyQt5.QtCore import (Qt)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
    QVBoxLayout, QApplication)


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def printLabel(self, str):
        print(str)

    def initUI(self):

        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)

        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)

        #This line works
        sld.valueChanged.connect(lcd.display)

        #This line does not work
        #sld.valueChanged.connect(lcd.display, self.printLabel("hi"))

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal & slot')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

解决方案

Taking your points in order:

  • The Qt5 documentation contains at least 90% of what you need to know, so there's little point in repeating it all in the PyQt5 documentation, which instead mainly concentrates on the features that are specific to PyQt (see the Signals and Slots article, for instance). Qt5 is a C++ library. You don't need to know C++ in order to use PyQt (or to read Qt's excellent documentation), but you can hardly expect to avoid it altogether.

  • The QSlider.valueChanged signal sends an int value to all the slots that are connected to it. The QLCDNUmber.display slot receives either a string, int or float object (i.e. it has three overloads). For built-in Qt slots, there must be an overload that matches what the signal sends. But user-defined slots in PyQt can be any python callable object, and it doesn't matter if the signature doesn't match (any extra parameters will be thrown away). Having said that, an explicit signature can be defined for a user-defined slot by using the pyqtSlot decorator (which therefore allows multiple overloads to be specified in PyQt).

  • As explained in the first section of the PyQt article mentioned above, both signals and slots can have multiple connections. The article also details the PyQt-specific APIs (including pyqtSlot), and gives examples of how to use them.

Here's how to connect to multiple slots your example:

class Example(QWidget):    
    ...

    def initUI(self):
        ...

        #connect to a built-in slot
        sld.valueChanged.connect(lcd.display)

        #connect to a user-defined lot
        sld.valueChanged.connect(self.printLabel)

        #any python callable will do
        sld.valueChanged.connect(lambda x: print('lambda:', x))

        ...            

    def printLabel(self, value):
        print('printLabel:', value)

这篇关于PyQt5 一信号多槽的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆