繁体   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