PyQt4 信号和槽

发布于 2024-08-17 05:18:42 字数 458 浏览 6 评论 0 原文

我正在使用 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")

不幸的是,没有调用插槽。我也尝试了不带参数的不同风格的发射信号。代码中没有错误,没有警告。可能是什么问题?

I am writing my first Python app with PyQt4. I have a MainWindow and a Dialog class, which is a part of MainWindow class:

self.loginDialog = LoginDialog();

I use slots and signals. Here's a connection made in 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):

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

你又不是我 2024-08-24 05:18:42

有一些概念需要澄清

【QT信号&信号】槽]VS【Python信号&槽】 slot]

所有预定义的信号& pyqt提供的槽是由QT的c++代码实现的。每当您想要定制信号时Python中的slot,它是一个python信号&投币口。因此,有四种情况可以向槽发出信号:

  • 从 QT 信号到 QT 槽
  • 从 QT 信号到 Python 槽
  • 从 Python 信号到 QT 槽
  • 从 Python 信号到 Python 槽

下面的代码显示了如何连接这四种不同的场景

    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 信号是在您发出信号时创建的。

对于slot来说,签名有三种形式。

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

数字 1 & 2 可用于 Python 槽,而数字 2 和 2 可用于 Python 槽。 3 个可用于 QT 插槽。很明显,除了 QT 预定义槽之外,任何 Python 可调用函数/方法都被限定为 Python 槽。

Summerfield 关于信号和槽的文章中提出了这些观点。

[旧式qt信号&]槽]VS[新风格qt信号&槽] slot]

好吧,上面的所有描述都是基于旧式的 pyqt signal & slot 。投币口。正如 @Idan K 所建议的,有一种替代的新风格可以完成这些事情,特别是对于 Python 信号。请参阅此处了解更多信息。

There are some concepts to be clarified

[QT signal & slot] VS [Python signal & slot]

All the predefined signals & slots provided by pyqt are implemented by QT's c++ code. Whenever you want to have a customized signal & slot in Python, it is a python signal & slot. Hence there are four cases to emits a signal to a slot:

  • from a QT signal to a QT slot
  • from a QT signal to a Python slot
  • from a Python signal to a QT slot
  • from a Python signal to a Python slot

The code below shows how to connect for these four different 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. The Python signal is created when you emit it.

For slot, there are three forms of signatures.

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

Number 1 & 2 are available for Python slot, while number 2 & 3 are available for QT slot. It is clear that besides QT predefined slot, any python callable function/methods is qulified to be a Python slot.

These points are made in Summerfield's article on Signals and Slots.

[Old style qt signal & slot] VS [new style qt singal & slot]

Well, all the description above is based on the old style pyqt signal & slot. As @Idan K suggested there is an alternative new-style to do the things, especially for the Python signal. Refer to here for more.

倾城花音 2024-08-24 05:18:42

发射和连接时不使用相同的信号。

QtCore.SIGNAL("aa(str)")QtCore.SIGNAL("aa") 不同。信号必须具有相同的签名。顺便说一句,如果您定义自己的信号,则不要定义参数。只需编写 SIGNAL('aa') 即可,因为定义参数是 C++ 中的事情,而 Python 版本的 Qt 不需要这个。

所以它应该是这样的:

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

如果你在emit中传递任何参数,你的登录方法必须接受这些参数。检查一下这是否有帮助:-)

You don't use the same signal, when emitting and connecting.

QtCore.SIGNAL("aa(str)") is not the same as 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.

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. Check, if this helps :-)

小瓶盖 2024-08-24 05:18:42

我检查了您的代码,问题似乎出在您连接信号的方式

  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;您最初的 connect 调用使用的是 LoginDialog 类型的 self.loginDialog,而信号是由 Ui_Dialog 类发出的,该类是 LoginDialog 的 ui 属性。在此更改 Ui_MainWindow 的登录方法后被调用

希望这有帮助,问候

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

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

  2. you connect to the signal in Ui_MainWindow's setupUi method by calling

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

notice first parameter is changed to 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. After this change login method of the Ui_MainWindow got called

hope this helps, regards

无边思念无边月 2024-08-24 05:18:42

@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 中如何工作的更详细说明,我建议阅读它的文档,特别是 本节

What @bialix suggested should have worked, but try an alternative way of connecting:

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.

梦里寻她 2024-08-24 05:18:42

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

As noted by gruszczy you have to use the same QtCore.SIGNAL('xxx') to connect signal and to emit it. Also I think you should use Qt types in the arguments list of signal function. E.g.:

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")
删除→记忆 2024-08-24 05:18:42

我没有使用过 PyQT4,但请查看此处

I haven't used PyQT4 but take a look at here.

只是偏爱你 2024-08-24 05:18:42

看起来您错过了连接呼叫中的“SLOT”部分。

这是一个例子:

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

然后

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

希望这会有所帮助!

Looks like you miss the "SLOT" part in your connect call.

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 !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文