簡體   English   中英

PyQt4信號和插槽

[英]PyQt4 signals and slots

我正在用PyQt4編寫我的第一個Python應用程序。 我有一個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")

不幸的是,沒有調用插槽。 我嘗試了沒有任何參數,不同風格的發射信號。 代碼中沒有錯誤,沒有警告。 可能是什么問題?

有一些概念需要澄清

[QT信號和插槽] VS [Python信號和插槽]

pyqt提供的所有預定義信號和插槽均由QT的c ++代碼實現。 每當你想在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槽。

這些觀點是在Summerfield關於信號和插槽的文章中提出的

[舊式qt信號和插槽] VS [新款qt信號和插槽]

好吧,上面的所有描述都基於舊式pyqt信號和插槽。 正如@Idan K建議的那樣,有一種新的方式可以做到這一點,特別是對於Python信號。 請參閱此處了解更多信息。

發射和連接時,不要使用相同的信號。

QtCore.SIGNAL("aa(str)")QtCore.SIGNAL("aa") 信號必須具有相同的簽名。 順便說一句,如果您要定義自己的信號,請不要定義參數。 只寫SIGNAL('aa'),因為定義參數是來自C ++的東西,而Qt的Python版本不需要這個。

所以看起來應該是這樣的:

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

如果你在emit中傳遞任何參數,你的登錄方法必須接受這些參數。 檢查,如果這有幫助:-)

@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. 你在Ui_Dialog類中發出信號

    self.emit(QtCore.SIGNAL( “AA()”))

  2. 你通過調用連接到Ui_MainWindow的setupUi方法中的信號

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

注意第一個參數改為self.loginDialog.ui ; 你的原始連接調用是使用了LoginDialog類型的self.loginDialog,而信號是由Ui_Dialog類發出的,它是LoginDialog的ui屬性。 在此更改之后調用Ui_MainWindow的登錄方法

希望這有幫助,問候

正如gruszczy所指出的,你必須使用相同的QtCore.SIGNAL('xxx')連接信號並發出它。 另外我認為你應該在信號函數的參數列表中使用Qt類型。 例如:

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")

我沒有使用過PyQT4,但請看一下這里

看起來你錯過了通話中的“SLOT”部分。

這是一個例子:

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

然后

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

希望這可以幫助 !

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM