How to check main event loop is running?



  • Hello there,

    I need to perform some action with X11, to manage a window created with PyQt4. This action cannot be done before the event-loop has begun, and it has to be done asap after the window has been painted on the screen.
    I managed to do this already by launching a QThread in my topmost widget's constructor. The QThread will keep polling until the window is hosted by X Window Manager, and then it performs the actions i need it to do.
    However, i thought it'd be nicer to use event-handling rather than event-polling. So i would like my top-level QWidget to receive a signal as soon as the event-loop begins. I've understood that using postEvent() would be useful since the event will be released as soon as the event-loop will begin. But i am not sure yet as to how i should use that.

    For now i call the postEvent in the main function like so:

    @app = QtGui.QApplication(sys.argv)

    def main():
    widget = MyWidget()
    widget.show()
    # now i assume this should successfully post the event:
    # i chose the ApplicationActive event, is it correct?
    app.postEvent(widget, QtCore.QEvent(QtCore.QEvent.ApplicationActivate))
    # then i connect the event to the widget:
    widget.connect(app, QtCore.SIGNAL('ApplicationActivate'),
    widget, QtCore.SLOT('on_loop')) # the on_loop is my widget's callback
    sys.exit(app.exec_())@

    In the Widget definition, the callback is defined so:

    @def on_loop(self, event):
            print 'event received is:', event@
    

    Of course, it doesn't work, otherwise i wouldn't be here :)
    I'm new to Qt4, not very familiar with signal-slot yet. Another idea i got was perhaps to send the event from my widget constructor, to itself. But i'm again unsure as to how i should implement that.

    I'd like some guidance, thanks :)

    Benjamin



  • I'm usually using QTimer::singleShot() to postpone actions until the event loop is running (and iddle;).



  • Yep, it's what i did, but with a QThread and a while loop. But i wanted to find a more secure way to do that.



  • First of all a event is not a signal. You can not connectec a Event with slot.

    To intercept the event you need to reimplement the function:
    'event (QEvent e) ' on your QWidget class. then you can check if the event received is the event which you have sent.



  • Another way to know when your widget was showed is re implement the function: showEvent (QShowEvent event ).



  • @Renato: the QShowEvent() is reveived before the window is actually hosted on X. I'll stick the QThread technique which works anyway. At least i've learnt something about event handling :) Thanks.



  • unclewerner is right, use the static method "QTimer::singleShot() ":http://doc.qt.nokia.com/4.7/qtimer.html#singleShot. Once it fires, it calls the slot given in the arguments:

    Supposed (from your Python code), you want to call slot on_loop() in object widget once the event loop runs, add this code somewhere in your app:

    @
    QTimer::singleShot(0, widget, "on_loop");
    @

    This all works without threads and sending events manually.



  • @ unclewerner & @ Volker: you seem to prefer QTimer to QThread: is there any advantage using one or the other? is QTimer not a thread with a loop?



  • Timers are processed in the event loop, so the slot will be called once the event loop is running. No Threads needed.



  • [quote author="jesuisbenjamin" date="1307145093"]@ unclewerner & @ Volker: you seem to prefer QTimer to QThread: is there any advantage using one or the other? is QTimer not a thread with a loop?[/quote]

    Why do it complicated, when there is a simple solution? You can easily shoot yourself into the foot with a QThread, but it's hard with a QTimer. I don't care about the actual implementation of QTimer's singleShot - it just works.

    But if you prefer to implement a QThread based code with some 10s of lines, compared to a one liner... it's your choice.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.