简体   繁体   English

PyQt4信号和插槽

[英]PyQt4 signals and slots

I am writing my first Python app with PyQt4. 我正在用PyQt4编写我的第一个Python应用程序。 I have a MainWindow and a Dialog class, which is a part of MainWindow class: 我有一个MainWindow和一个Dialog类,它是MainWindow类的一部分:

self.loginDialog = LoginDialog();

I use slots and signals. 我使用插槽和信号。 Here's a connection made in MainWindow: 这是MainWindow中的连接:

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

And I try to emit signal inside the Dialog class (I'm sure it is emitted): 我尝试在Dialog类中发出信号(我确定它已发出):

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

Unfortunately, slot is not invoked. 不幸的是,没有调用插槽。 I tried with no arguments as well, different styles of emitting signal. 我尝试了没有任何参数,不同风格的发射信号。 No errors, no warnings in the code. 代码中没有错误,没有警告。 What might be the problem? 可能是什么问题?

There are some concepts to be clarified 有一些概念需要澄清

[QT signal & slot] VS [Python signal & slot] [QT信号和插槽] VS [Python信号和插槽]

All the predefined signals & slots provided by pyqt are implemented by QT's c++ code. pyqt提供的所有预定义信号和插槽均由QT的c ++代码实现。 Whenever you want to have a customized signal & slot in Python, it is a python signal & slot. 每当你想在Python中拥有一个自定义信号和插槽时,它就是一个python信号和插槽。 Hence there are four cases to emits a signal to a slot: 因此,有四种情况可以向插槽发送信号:

  • from a QT signal to a QT slot 从QT信号到QT时隙
  • from a QT signal to a Python slot 从QT信号到Python插槽
  • from a Python signal to a QT slot 从Python信号到QT插槽
  • from a Python signal to a Python slot 从Python信号到Python插槽

The code below shows how to connect for these four different scnarios 下面的代码显示了如何连接这四种不同的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())

Conclusion is -- 结论是 -

Signal signature for Python signal differentiate from that of QT signal in that it doesn't have the parenthesis and can be passed any python data types when you emit it. Python信号的信号签名与QT信号的信号签名不同,因为它没有括号,并且在发出时可以传递任何python数据类型。 The Python signal is created when you emit it. 发出Python信号时会创建它。

For slot, there are three forms of signatures. 对于插槽,有三种形式的签名。

  • s.connect(w, SIGNAL("signalSignature"), functionName) s.connect(w,SIGNAL(“signalSignature”),functionName)
  • s.connect(w,SIGNAL("signalSignature"), instance.methodName) s.connect(w,SIGNAL(“signalSignature”),instance.methodName)
  • s.connect(w,SIGNAL("signalSignature"), instance, SLOT("slotSignature")) s.connect(w,SIGNAL(“signalSignature”),实例,SLOT(“slotSignature”))

Number 1 & 2 are available for Python slot, while number 2 & 3 are available for QT slot. 1号和2号可用于Python插槽,而2号和3号可用于QT插槽。 It is clear that besides QT predefined slot, any python callable function/methods is qulified to be a Python slot. 很明显,除了QT预定义槽之外,任何python可调用函数/方法都被称为Python槽。

These points are made in Summerfield's article on Signals and Slots . 这些观点是在Summerfield关于信号和插槽的文章中提出的

[Old style qt signal & slot] VS [new style qt singal & slot] [旧式qt信号和插槽] VS [新款qt信号和插槽]

Well, all the description above is based on the old style pyqt signal & slot. 好吧,上面的所有描述都基于旧式pyqt信号和插槽。 As @Idan K suggested there is an alternative new-style to do the things, especially for the Python signal. 正如@Idan K建议的那样,有一种新的方式可以做到这一点,特别是对于Python信号。 Refer to here for more. 请参阅此处了解更多信息。

You don't use the same signal, when emitting and connecting. 发射和连接时,不要使用相同的信号。

QtCore.SIGNAL("aa(str)") is not the same as QtCore.SIGNAL("aa") . QtCore.SIGNAL("aa(str)")QtCore.SIGNAL("aa") Signals must have the same signature. 信号必须具有相同的签名。 By the way, if you are defining your own signals, don't define parametres. 顺便说一句,如果您要定义自己的信号,请不要定义参数。 Just write SIGNAL('aa'), because defining parametres is a thing from C++ and Python version of Qt doesn't need this. 只写SIGNAL('aa'),因为定义参数是来自C ++的东西,而Qt的Python版本不需要这个。

So it should look like this: 所以看起来应该是这样的:

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

and if you pass any parametres in emit, your login method must accept those parametres. 如果你在emit中传递任何参数,你的登录方法必须接受这些参数。 Check, if this helps :-) 检查,如果这有帮助:-)

What @bialix suggested should have worked, but try an alternative way of connecting: @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

For a more detailed explanation of how signals/slots work in PyQt I'd suggest going through it's documentation, specifically this section . 有关信号/插槽如何在PyQt中工作的更详细说明,我建议通过它的文档,特别是本节

I checked your code and it looks like the problem is in the way how you're connecting your signal 我检查了你的代码,看起来问题就在于你如何连接你的信号

  1. you emit the signal in Ui_Dialog class 你在Ui_Dialog类中发出信号

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

  2. you connect to the signal in Ui_MainWindow's setupUi method by calling 你通过调用连接到Ui_MainWindow的setupUi方法中的信号

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

notice first parameter is changed to self.loginDialog.ui ; 注意第一个参数改为self.loginDialog.ui ; your original connect call was using self.loginDialog which is of the LoginDialog type, whereas signal is emitted by the Ui_Dialog class which is ui property of the LoginDialog. 你的原始连接调用是使用了LoginDialog类型的self.loginDialog,而信号是由Ui_Dialog类发出的,它是LoginDialog的ui属性。 After this change login method of the Ui_MainWindow got called 在此更改之后调用Ui_MainWindow的登录方法

hope this helps, regards 希望这有帮助,问候

As noted by gruszczy you have to use the same QtCore.SIGNAL('xxx') to connect signal and to emit it. 正如gruszczy所指出的,你必须使用相同的QtCore.SIGNAL('xxx')连接信号并发出它。 Also I think you should use Qt types in the arguments list of signal function. 另外我认为你应该在信号函数的参数列表中使用Qt类型。 Eg: 例如:

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

And then emit with: 然后发出:

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

Sometimes it makes sense to define signal only once as global variable and use it elsewhere: 有时仅将信号定义为全局变量并在其他地方使用它是有意义的:

MYSIGNAL = QtCore.SIGNAL("aa(QString&)")
...
QtCore.QObject.connect(self.loginDialog, MYSIGNAL, self.login)
...
self.emit(MYSIGNAL, "jacek")

我没有使用过PyQT4,但请看一下这里

Looks like you miss the "SLOT" part in your connect call. 看起来你错过了通话中的“SLOT”部分。

Here is an example : 这是一个例子:

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

then 然后

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

Hope this helps ! 希望这可以帮助 !

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM