[PyQt] Simple polling monitor application

Eric Frederich eric.frederich at gmail.com
Fri Jul 19 15:23:32 BST 2013


I thought that signals get processed on the same thread that the GUI runs in.
So in connecting the timer's timeout signal to self.get_stuff, then
wouldn't the get_stuff method run on the same GUI thread?
The point of using another thread was to do the actual long-running
work in the other thread.
I think with what you suggested only starting the timer would be done
in another thread, not the actual work.

Of course I could be entirely wrong.

On Fri, Jul 19, 2013 at 9:37 AM, David Hoese <dhoese at gmail.com> wrote:
> Hi Eric,
>
> One thing that was recommended to me when I started doing monitoring GUIs
> was to use a QTimer of 0 to call the polling function. To do this for your
> code, move everything in the "while True" into it's own function and make it
> run on a per-iteration way. So in your example, "count" would become an
> instance attribute and I think that's it.
>
> Then in the run method you would create a QTimer and set it to call that new
> per-iteration function:
>
>     self.my_timer = QtCore.QTimer()
>     self.my_timer.timeout.connect(self.get_stuff)
>     self.my_timer.start(0) # or some amount of delay
>
> The 0 delay makes it continuously add the "get_stuff" method to the event
> loop. This should do what you want. You may run in to trouble when closing
> the GUI if your polling does any kind of blocking. Once you tell the thread
> to stop (an event in the event loop) the thread won't get to that event
> until the blocking operation is complete. Depending on the length of the
> blocking, your GUI could hang on close for a little bit. There are ways
> around this, but I haven't found one that I love. Hopefully that made sense.
>
> Please CC me in any replies, thanks.
>
> -Dave
>
> P.S. I'll point you to a blog post about not subclassing QThread as the
> preferred method (get your stuff working first):
> http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
>
>
> On 7/19/2013 6:00 AM, eric.frederich at gmail.com wrote:
>>
>> Hello,
>>
>> I wrote an example monitoring application where I have a separate
>> thread monitoring something via an external process which could take
>> 20ms to run or it could take 2 seconds to run.
>> Right now I have it just doing a time.sleep(1) for the example.
>>
>> I want this monitoring to continuously happen.
>> It is an endless (while True) loop.
>> I'd prefer to use a QTimer but don't know how to get a QTimer to
>> trigger something in another thread.
>> The work needs to be done in another thread to keep the GUI responsive.
>>
>> Can someone point me in the right direction or modify the following
>> code to use a QTimer rather than an infinite loop with a sleep
>> command?
>>
>>
>> #!/usr/bin/env python
>>
>> from PyQt4.QtCore import *
>> from PyQt4.QtGui import *
>>
>> import time
>> from datetime import datetime
>>
>> class MyThread(QThread):
>>      def __init__(self, parent=None):
>>          super(MyThread, self).__init__(parent)
>>
>>      def run(self):
>>          count = 0
>>          while True:
>>              count += 1
>>              print 'do_something ', count, 'begin'
>>              time.sleep(1)
>>              self.emit(SIGNAL("new_info"), str(count) + ' ' +
>> str(datetime.now()))
>>              print 'do_something ', count, 'end'
>>
>> class MyWidget(QWidget):
>>      def __init__(self, parent=None):
>>          super(MyWidget, self).__init__(parent)
>>          self.setWindowTitle("Monitor")
>>          layout = QVBoxLayout()
>>          self.line = QLineEdit()
>>          layout.addWidget(self.line)
>>          self.setLayout(layout)
>>
>>          self.mon = MyThread()
>>          self.connect(self.mon, SIGNAL("new_info"), self.on_new_info)
>>          self.mon.start()
>>
>>      def on_new_info(self, info):
>>          print 'got new info', info
>>          self.line.setText(info)
>>
>> if __name__ == '__main__':
>>      import sys
>>      app = QApplication(sys.argv)
>>      gm = MyWidget()
>>      gm.show()
>>      sys.exit(app.exec_())


More information about the PyQt mailing list