0

I need to emit a signal periodically. A timer executes certain function, which emits the signal that I want. For some reason this function is not being emitted. I was able to reproduce the error on minimal code (see further down). If I do the same without the timer everything works:

from threading import Timer
import time
from PySide import QtCore

class testSignals(QtCore.QObject):
    signal = QtCore.Signal();
    def __init__(self):
        QtCore.QObject.__init__(self)

    def run(self):
        self.signal.emit()

class testConnection():
    @QtCore.Slot()
    def receiveMe(self):
        print('Signal received')

    # signal is emmited when data is changed
    def __init__(self):
        test = testSignals()
        test.signal.connect(self.receiveMe)
        test.run();

test = testConnection()

I was able to reproduce my problem in the following code:

from threading import Timer
import time
from PySide import QtCore

class testSignals(QtCore.QObject):

    signal = QtCore.Signal();

    def __init__(self):
        self.is_running = False
        QtCore.QObject.__init__(self)
        self.start()

    def emitMe(self):
        self.is_running = False
        self.start()
        # print("emitMe")
        self.signal.emit()

    def start(self):
        if not self.is_running:
            self._timer = Timer(0.2, self.emitMe)
            self._timer.start()
            self.is_running = True

    def stop(self):
        self._timer.cancel()
        self.is_running = False

class testConnection():
    @QtCore.Slot()
    def receiveMe(self):
        print('Signal received')

    # signal is emmited when data is changed
    def __init__(self):
        test = testSignals()
        test.signal.connect(self.receiveMe)
        test.start();
        time.sleep(2.0)
        test.stop();

test = testConnection()

the phrase "Signal received" does not get printed on the screen.

cauchi
  • 1,463
  • 2
  • 17
  • 45
  • Signals won't work without an event-loop. – ekhumoro May 18 '15 at 16:22
  • could you elaborate that? I think it happens because the thread is outside the control of Qt, but I haven't found a way to solve it. I going over this: http://stackoverflow.com/questions/9712461/pyside-wait-for-signal-from-main-thread-in-a-worker-thread – cauchi May 18 '15 at 16:34
  • 2
    For direct signal/slot connections, an event-loop is not needed (or even an application object). But for cross-thread connections, the signals are posted to an event-queue and processed asynchronously. Of course, you will probably need to use a `QThread` for that - although I suppose it might be possible to hack together some kind of work-around (don't ask me how). But anyway: why aren't you using `QTimer`? – ekhumoro May 18 '15 at 17:18

1 Answers1

2

As @ekhumoro said in the comments, QTimer helped a lot. I needed an event-loop. I'm posting the code to make the answer valid. I rewrote it using QTimer, which made everything simpler really. Note that I need to call QCoreApplication to run the threads. Again, this is just the minimal code to reproduce what I needed to do.

import time
from PySide import QtCore
from probeConnection import ProbeConnection 

class testSignals(QtCore.QObject):

    def __init__(self):
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.tick)
        self.start()

    def tick(self):
        print("tick")

    def getData(self):
        return time.strftime('%H:%M:%S')

    def start(self):
        self.timer.start(1000)

    def stop(self):
        self.timer.stop()

class testConnection():
    def receiveMe(self):
        print('time: ' + self.test.getData())

    def __init__(self):
        self.test = testSignals()
        self.test.timer.timeout.connect(self.receiveMe)


app = QtCore.QCoreApplication([])
test = testConnection()
timer = QtCore.QTimer()
timer.singleShot(4000,app.exit)
app.exec_()

it produces:

tick
time: 13:23:37
tick
time: 13:23:38
tick
time: 13:23:39
tick
time: 13:23:40
cauchi
  • 1,463
  • 2
  • 17
  • 45