Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

qt - PyQt5 one signal and multiple slots

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_())
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...