1

I recently switched from wxPython to PyQT and can't find an equivalent of CallAfter. I need to use pubsub due to some imports and with wx I just sent messages with CallAfter -- is there a way to do something similar in PyQT? Basically, I want to inject something into the mainloop with pyQT.

EDIT FOR MORE INFO:

In my old GUI, using wxPython, I was using python-openzwave which uses an old dispatcher module. I would capture the old dispatcher signals and convert them to pubsub messages (for ease of use) and send the new messages with a CallAfter like this:

wx.CallAfter(pub.sendMessage, messagePack.signal, message = messagePack.message)

And then I was able to update the GUI by capturing the message and working directly on the gui elements because it essentially injected something into the mainloop.

Now, using pyqt, there is no callafter so, I have the same system setup without the callafter but the actions that have to occur after the message is received can't happen because it is in the middle of the mainloop.

linus72982
  • 1,418
  • 2
  • 16
  • 31
  • Could you add a bit more detail on why you need to do this (are you using threads? If so what for? If not, what is it you are doing?)? There are a couple of solutions and the correct one depends on what you are doing. – three_pineapples Jan 22 '16 at 23:08
  • 2
    Signals and slots are automatically thread-safe in Qt, so there's no real equivalent (i.e. no need for one). – ekhumoro Jan 22 '16 at 23:12
  • For example, python-openzwave uses a pubsub system to send updates about sensors and the like. When a sensor updates, I need it to be able to update the GUI. I'm guessing a converter function subscribing to the messages and resending them as pyqt emits would do the trick? It seems like a step I shouldn't need. – linus72982 Jan 22 '16 at 23:21
  • @linus72982. The "pubsub" stuff is really confusing the issue. Can you provide a much simpler example that demonstrates some of the specific problems you are unable to solve? That is, something like the wx wiki example for [CallAfter](http://wiki.wxpython.org/CallAfter). – ekhumoro Jan 22 '16 at 23:34
  • I updated the question with a bit more info. I didn't add much code because there is tons of code doing this work. Hopefully the explanation is good enough. – linus72982 Jan 23 '16 at 00:02
  • 1
    @linus72982. I'm afraid I can't see what the problem is. Define a custom signal, and connect it to a slot in the gui; then simply emit a signal with the message whenever appropriate. – ekhumoro Jan 23 '16 at 00:24

1 Answers1

3

The closest thing I can think of is using QTimer.singleShot with a short timeout, which will force it into the next event loop.

def other_function(self):
    print 'other'

def my_function(self):
    print 'one'
    QTimer.singleShot(1, self.other_function)
    print 'two'

Qt has the idea of an event loop, where it will check if there are events that need processing, like a button click, or part of a widget needs to be redrawn, etc. Typically, a function gets called as the result of an event. The QTimer.singleShot will stick your function call at the end of the list of things to be processed on the next cycle of the event loop.

But I agree with some of the comments that you probably could just use a separate QObject running in another thread to handle the openzwave events and re-dispatch the messages as Qt Signals, which the main thread can listen for and update the GUI.

Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • That singleShot might have worked but I decided to just go back to wxPy. The problem with just making a QObject and sending the signals as emits is: 1) I switch completely to emits, this has the problem that all other messages, some that have zero to do with the gui, are now processing through QObjects. 2) I pubsub some messages and emit others -- this requires the sender to know the receiver, however, bad form. 3) I duplicate all messages as pubsubs and emits. Or I can just use the fancy CallAfter in the comparable wx. The last option sounded the most sane. – linus72982 Jan 24 '16 at 21:58
  • And, to be honest, I greatly enjoyed the more extensive documentation and support out there for wx. I liked that qt seemed a bit more smooth in development, but wx just has too much information out there. – linus72982 Jan 24 '16 at 22:00
  • QObjects aren't GUI dependent, its fine to use QObjects and Signals for non-GUI stuff. I dont understand the next part. Why does the sender need to know the receiver? And why is it bad form? What are pubsubs? It's funny, I always found the Qt docs examples to more comprehensive than wx, but Qt is kind of a standard in my industry, so that may have had something to do with it. – Brendan Abel Jan 24 '16 at 23:17
  • I guess I could use signals for non-gui, I just like the pubsub module better as I can capture categories of messages. For example, I could have SENSOR.FRONTDOOR.OPEN and pick it up by subscribing to "SENSOR" or all front door actions with "SENSOR.FRONTDOOR". The sender has to know the receiver because in that option I mentioned, I would have to send some messages as qt signals and some as pubsub messages, so the sender would have to know where it's going. That's bad form because it's tightly coupled. PyPubSub is a module that allows messages to be sent back and forth. It's in PyPi. – linus72982 Jan 24 '16 at 23:28
  • I don't think your using Qt Signals right. The sender should never have to know anything about the receiver. The sender emits signals, the receiver subscribes to them. I don't know of anything in Qt that does nested events like SIGNAL.SUBSIGNAL.SUBSIGNAL, that sounds pretty cool, but I'm sure it wouldn't be hard to add that type of syntax sugar. I think an easier way to do it in Qt would be to include that information in the signal, and just have the receiver filter out the ones it doesn't care about. – Brendan Abel Jan 24 '16 at 23:36
  • I understand that qt signals are a publish/subscribe model. What I was saying was that in my option #2 above, I explain that I could pubsub some messages and use qt signals for others. The problem is that to know which I should use pubsub (business logic) and which I should use qt signals (gui), the sender would have to tell the sending module if they were a gui message or a logic message. Hence, the sender would have to know where it would ultimately end up. This is all assuming I split all messages into two categories, qt for gui stuff and pubsub for everything else. – linus72982 Jan 24 '16 at 23:43