PyQt5 один сигнал и несколько слотов

Я придумал простой механизм сигнала / слота ниже. Сигнал вызывается QSlider, когда значение изменяется с помощью QSlider::valueChanged(). И слот вызывается через метод QLCDNumber::display().

Что меня смущает, так это то, что в PyQt5 так мало документации, и большая часть документации ведет к ссылкам на Qt5. У меня есть конкретная проблема с кодом:

1) Если QSlider:: valueChanged () (signal) ожидает целое число в качестве параметра, почему мы передаем только QLCDNumber::display() (slot), который является функцией void. Поэтому ничего не будет передано.

2) В закомментированном коде ниже я не могу вызвать второй слот. Есть ли ограничение на количество слотов, которые вы можете вызвать для одного сигнала? Если есть, как я могу вызвать несколько слотов в PyQt5.

Редактировать: я считаю, потому что printLabel () не определенный слот, поэтому я получаю проблемы. Можно ли включить любое количество слотов в параметры:: connect ()? Или я подхожу к этому хакерски.

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_())

1 ответ

Решение

Принимая ваши очки в порядке:

  • Документация Qt5 содержит как минимум 90% того, что вам нужно знать, поэтому нет смысла повторять все это в документации PyQt5, которая в основном концентрируется на функциях, специфичных для PyQt (см., Например, статью " Сигналы и слоты").). Qt5 - это библиотека C++. Вам не нужно знать C++, чтобы использовать PyQt (или читать отличную документацию Qt), но вряд ли вы вообще можете этого избежать.

  • QSlider.valueChanged сигнал посылает значение int всем слотам, которые к нему подключены. QLCDNUmber.display Слот получает объект типа string, int или float (то есть имеет три перегрузки). Для встроенных слотов Qt должна быть перегрузка, которая соответствует тому, что посылает сигнал. Но пользовательские слоты в PyQt могут быть любыми вызываемыми объектами Python, и не имеет значения, не совпадает ли подпись (любые дополнительные параметры будут выброшены). Сказав это, явная подпись может быть определена для пользовательского слота с помощью pyqtSlot декоратор (который поэтому позволяет указывать несколько перегрузок в PyQt).

  • Как объяснено в первом разделе статьи PyQt, упомянутой выше, и сигналы, и слоты могут иметь несколько соединений. В статье также подробно описываются специфичные для PyQt API-интерфейсы (включая pyqtSlot) и приводит примеры их использования.

Вот как можно подключить несколько слотов на вашем примере:

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)
Другие вопросы по тегам