PyQt4 сигналы и слоты - PullRequest
       21

PyQt4 сигналы и слоты

6 голосов
/ 12 января 2010

Я пишу свое первое приложение на Python с PyQt4. У меня есть MainWindow и класс Dialog, который является частью класса MainWindow:

self.loginDialog = LoginDialog();

Я использую слоты и сигналы. Вот соединение, выполненное в MainWindow:

QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa(str)"), self.login)

И я пытаюсь излучать сигнал внутри класса Dialog (я уверен, что он излучается):

self.emit(QtCore.SIGNAL("aa"), "jacek")

К сожалению, слот не вызывается. Я также пытался без аргументов, разные стили испускания сигнала. Нет ошибок, нет предупреждений в коде. В чем может быть проблема?

Ответы [ 7 ]

26 голосов
/ 01 октября 2011

Есть некоторые понятия, которые необходимо уточнить

[сигнал и слот QT] VS [сигнал и слот Python]

Все предопределенные сигналы и слоты, предоставляемые pyqt, реализованы с помощью кода C ++ QT. Всякий раз, когда вы хотите иметь настраиваемый сигнал и слот в Python, это сигнал и слот Python. Следовательно, есть четыре случая для подачи сигнала в слот:

  • из сигнала QT в слот QT
  • из сигнала QT в слот Python
  • от сигнала Python до слота QT
  • от сигнала Python до слота Python

Код ниже показывает, как подключиться к этим четырем различным scnarios

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *

    class Foo(QtCore.QObject):

        def __init__(self, parent=None):
            super(Foo, self).__init__(parent)
            dial = QDial()
            self.spinbox = QSpinbox()

            # --------------------------------------
            # QT signal & QT slot
            # --------------------------------------

            # option 1: more efficient 
            self.connect(self.spinbox, SIGNAL("valueChanged(int)"), 
                dial, SLOT("setValue(int)"))
            # option 2:
            self.connect(self.spinbox, SIGNAL("valueChanged(int)"), 
                dial.setValue)


            # --------------------------------------
            # QT signal & Python slot
            # --------------------------------------

            self.connect(self.spinbox, SIGNAL("valueChanged(int)"), 
                self.myValChanged)


            # --------------------------------------
            # Python signal & Qt slot
            # --------------------------------------

            # connect option 1: more efficient
            self.connect(self, SIGNAL("mysignal"), dial, 
                SLOT("setValue(int)"))

            # connect option 2:
            self.connect(self, SIGNAL("mysignal"), dial.setValue)

            # emit
            param = 100
            self.emit(SIGNAL("mysignal"), param)


            # --------------------------------------
            # Python signal & Python slot
            # --------------------------------------

            # connect
            self.connect(self, SIGNAL("mysignal"), self.myValChanged)

            # emit
            param = 100
            self.emit(SIGNAL("mysignal"), param)


    def myValChanged(self):
        print "New spin val entered {0}".format(self.spinbox.value())

Вывод -

Сигнатура сигнала для сигнала Python отличается от сигнатуры сигнала QT тем, что он не имеет круглых скобок и может передаваться любым типам данных python при его излучении. Сигнал Python создается при его излучении.

Для слота есть три вида подписей.

  • s.connect (w, SIGNAL ("signalSignature"), functionName)
  • s.connect (w, SIGNAL ("signalSignature"), instance.methodName)
  • s.connect (w, SIGNAL ("signalSignature"), экземпляр, SLOT ("slotSignature"))

Номера 1 и 2 доступны для слота Python, а номера 2 и 3 доступны для слота QT. Понятно, что кроме предопределенного слота QT любая функция / метод, вызываемый Python, квалифицируется как слот Python.

Эти пункты приведены в статье Саммерфилда о сигналах и слотах .

[сигнал и слот qt старого стиля] VS [сигнал и слот qt старого стиля]

Ну, все вышеприведенное описание основано на сигнале и слоте pyqt старого стиля. Как сказал @Idan K, есть альтернативный новый стиль, особенно для сигнала Python. Подробнее см. здесь

12 голосов
/ 12 января 2010

Вы не используете один и тот же сигнал при излучении и подключении.

QtCore.SIGNAL("aa(str)") - это не то же самое, что QtCore.SIGNAL("aa"). Сигналы должны иметь одинаковую подпись. Кстати, если вы определяете свои собственные сигналы, не определяйте параметры. Просто напишите SIGNAL ('aa'), потому что определение параметров - это вещь из C ++, и Python-версия Qt не нуждается в этом.

Так должно выглядеть так:

QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa"), self.login)

и если вы передадите какие-либо параметры в emit, ваш метод входа в систему должен принять эти параметры. Проверьте, помогает ли это: -)

3 голосов
/ 18 января 2010

Я проверил ваш код, и похоже, проблема в том, как вы подключаете свой сигнал

  1. вы излучаете сигнал в классе Ui_Dialog

    self.emit (QtCore.SIGNAL ( "аа ()"))

  2. вы подключаетесь к сигналу в методе setupUi Ui_MainWindow, вызывая

    QtCore.QObject.connect (self.loginDialog.ui, QtCore.SIGNAL ("aa ()"), self.login)

обратите внимание, что первый параметр изменен на self.loginDialog.ui ; Ваш исходный вызов соединения использовал self.loginDialog, который имеет тип LoginDialog, тогда как сигнал испускается классом Ui_Dialog, который является свойством пользовательского интерфейса LoginDialog. После этого изменения метод входа в Ui_MainWindow называется

надеюсь, это поможет, с уважением

3 голосов
/ 12 января 2010

То, что предложил @bialix, должно сработать, но попробуйте альтернативный способ подключения:

class Foo(QtCore.QObject):
    mysignal = QtCore.pyqtSignal(str, name='mysignal')

    def connect_to_signal(self):
        # you can use this syntax instead of the 'old' one
        self.mysignal.connect(self.myslot)

        # but this will also work
        self.connect(self, QtCore.SIGNAL('mysignal(QString)'), self.myslot) 

        self.mysignal.emit("hello")

    def myslot(self, param):
        print "received %s" % param

Для более подробного объяснения того, как сигналы / слоты работают в PyQt, я бы посоветовал ознакомиться с его документацией, в частности в этом разделе .

1 голос
/ 12 января 2010

Как отметил gruszczy, вы должны использовать один и тот же QtCore.SIGNAL ('xxx') для подключения сигнала и его излучения. Также я думаю, что вы должны использовать типы Qt в списке аргументов сигнальной функции. E.g.:

QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa(QString&)"), self.login)

А затем с помощью:

self.emit(QtCore.SIGNAL("aa(QString&)"), "jacek")

Иногда имеет смысл определить сигнал только один раз как глобальную переменную и использовать его в другом месте:

MYSIGNAL = QtCore.SIGNAL("aa(QString&)")
...
QtCore.QObject.connect(self.loginDialog, MYSIGNAL, self.login)
...
self.emit(MYSIGNAL, "jacek")
0 голосов
/ 12 января 2010

Похоже, вы пропустили часть "SLOT" в вашем соединении.

Вот пример:

QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("NotifyMySignal(int)"), QtCore.SLOT("onNotifyMySignal(int)"));

затем

self.emit(QtCore.SIGNAL('NotifyMySignal(1)'));

Надеюсь, это поможет!

0 голосов
/ 12 января 2010

Я не использовал PyQT4, но посмотрите на здесь .

...