0

I have the following piece of code:

def callback(param):
    print "in callback"

class Test(QThread):
    def __init__(self):
        QThread.__init__(self)
        #QObject.connect(self, SIGNAL("test_signal(PyQt_PyObject)"), callback)
        print "Test constructed"

    def fallback(self, dummy=None):
        print "in fallback"

    def run(self):
        while 1:
            print "Test running"
            self.emit(SIGNAL("test_signal(PyQt_PyObject)"), {'a': 'b'})
            time.sleep(1)

t = None

if __name__ == "__main__":

    t = Test()
    t.start()
    QObject.connect(t, SIGNAL("test_signal(PyQt_PyObject)"), callback)
    while True:
        time.sleep(2)

However, callback(param) is never called, as in, I don't see the "in callback" printed on the console. Can anyone help with this? I've tried different variations of the code (e.g. removing the parameter from test_signal, connecting to self.fallback(), not including any paramters in self.emit (i.e. removing {'a': 'b'})). I must be missing a very simple but fundamental mechanism, but I just can't figure it out.

Thanks in advance!

Gerald T
  • 25
  • 5
  • I usually use C++ qt, but this doesn't look as proper definition and emission of signal with pyqt. Check this http://www.pythoncentral.io/pysidepyqt-tutorial-creating-your-own-signals-and-slots/ – Marek R Jan 22 '14 at 21:22

2 Answers2

2

You would have to declare your custom signal. This is a PySide example which is very similar to pyqt, but you may have to modify it. It also depends on the version. This is a Python 3.3 version with PySide 1.2.1

class Test(QThread):
    test_signal = QtCore.Signal(object)

...
    while 1:
        print "Test running"
        self.test_signal.emit({"a": "b"})

...
t.test_signal.connect(callback)
justengel
  • 6,132
  • 4
  • 26
  • 42
  • Thanks for the feedback. This is more useful for a PySide application, but has some application for PyQt as well. – Gerald T Jan 23 '14 at 14:48
2

If you want a thread to use signals you need to start an event loop, the more straightforward way is to start a QApplication:

from PyQt4.QtGui import QApplication
from PyQt4.QtCore import *
import time

@pyqtSlot(dict)
def callback(param):
    print "in callback"
    print param

class Test(QThread):

    mySignal =  pyqtSignal(dict,name="mySignal")

    def __init__(self):
        QThread.__init__(self)

    def run(self):
        while 1:
            print "Test running"
            self.mySignal.emit({'a': 'b'})
            time.sleep(1)

if __name__ == "__main__":
    t = Test()
    t.start()
    t.mySignal.connect(callback)
    app = QApplication([])
    app.exec_()
Alvaro Fuentes
  • 16,937
  • 4
  • 56
  • 68
  • For those who may be wondering about the different signal styles, you can find more info on new style signals [here](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html), and info on old style signals [here](http://pyqt.sourceforge.net/Docs/PyQt4/old_style_signals_slots.html). I found the comparison between old and new on the old page useful as well. – Gerald T Jan 23 '14 at 14:51
  • Can you provide an example of how to properly use an Eventloop, @xndrme, presumably `QEventloop`? I'm having a hard time finding something helpful on SO or Google. Thanks in advance – Gerald T Jan 23 '14 at 18:52
  • 1
    Humm, well, with event loop I wasn't referring to `QEventloop` the problem is that for using `QThread` you need to start a `QApplication` as stated [here](http://qt-project.org/doc/qt-4.8/qt4-threads.html), the idea is that if you want slots in your `Qthread`s you need to start an event loop per thread, (which is easy, just call `self.exec_()`) but maybe I wasn't clear in my answer sorry :(. Just keep in mind `QThread`s only if `QApplication`. (If you find a way of doing what you want without a `QApplication` just call me! ;) ) – Alvaro Fuentes Jan 24 '14 at 17:02