From: David H. <dh...@gm...> - 2011-12-14 14:45:51
|
I'm not sure how experienced you are with multithreaded programs, but here is some sample code (I mentioned it can get complicated). I suggest you research Qt4 QThreads and also Qt4 Signals and slots to better understand the code below. It is a working sample so you should be able to run it in a terminal and notice that the GUI is responsive and that you have messages being printed out on the terminal. The code I provided below is more complicated than you may need for a proof-of-concept kind of program, but if you will be communicating with physical devices I suggest something like this. I am by no means and expert, but I have been doing something similar to what you are doing. I also suggest maybe separating the device communication into another module/class, especially if others are going to (re)use your code. Good Luck, Dave P.S. There are a lot of Qt4/PyQt4 threading examples online, but not all of them correct. What I posted below is what I have found to be considered "correct" by most people. ################# ### Sample Code ### ################# import time from PyQt4 import QtGui,QtCore class MyWindow(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) # Sample GUI elements to test responsiveness the_choices = ["item"]*20 self.choices = QtGui.QComboBox() self.choices.addItems(the_choices) self.layout = QtGui.QVBoxLayout(self) self.layout.addWidget(self.choices) self.setLayout(self.layout) def handle_new_data(self): # This is where you could redraw any matplotlib plots # Maybe send data through the signal/slot connection print "Updating data" class MyInstrument(QtCore.QObject): signal_new_data = QtCore.pyqtSignal(name="signal_new_data") signal_closing = QtCore.pyqtSignal(name="signal_closing") def run(self): self._timer = QtCore.QTimer() self._timer.timeout.connect(self._run) self._timer.start(0) def _run(self): time.sleep(1) print "Running the instrument function" time.sleep(1) self.signal_new_data.emit() def close(self): print "Closing instrument thread" self._timer.stop() # Redundant timer stop self._timer.timeout.disconnect() self.signal_closing.emit() if __name__ == "__main__": app = QtGui.QApplication([" "]) w = MyWindow() w.show() instrument = MyInstrument() instrument_thread = QtCore.QThread() instrument.moveToThread(instrument_thread) instrument_thread.started.connect(instrument.run) instrument.signal_new_data.connect(w.handle_new_data) # Make the close function run in the main thread so you can "interrupt" the sleeps app.lastWindowClosed.connect(instrument.close, QtCore.Qt.DirectConnection) # You could also call quit "manually" after exec_() returns instrument.signal_closing.connect(instrument_thread.quit) instrument_thread.start() app.exec_() #instrument_thread.quit() print "Waiting for instrument thread..." instrument_thread.wait() print "SUCCESS" ###################### ### End of Sample Code ### ###################### On 12/14/11 3:51 AM, Fabien Lafont wrote: > I prefer to use the multi-thread method beacause it's easier for me > and my colaborators to have the entire acquisition process at the same > place. Until then I use a simple one but I hope to use a more complex > one in few weeks ( put different voltages on different devices then > measure many voltages or current). If I use the "domino" technique > (call the next operation by the end of the previous) it can be complex > to read and to edit. Thank you very much anyway! > > How can I write a multi-thread process? I've just tried to add > qApp.processEvents() at the end of my while loop but it doesn't change > anything... > > Thanks again, > > Fabien > > 2011/12/13 David Hoese<dh...@gm...>: >> Yeah I didn't think about suggesting that, but I think it might get >> complicated. I think he would have to start a one shot timer to call a >> function to set the voltage. Then that function would also start another >> one shot timer to call another function that would read from the sample. >> That function then would start a one shot timer to call the first function >> again. This way he can be sure that things are called in order and that >> timing is consistent, just in case the GUI gets complicated or something >> makes the event loop slow down. >> >> He could also use multiple threads. Whatever works for Fabien I guess. >> >> -Dave >> >> On 12/13/11 1:00 PM, mat...@li... wrote: >>> From: "Drain, Theodore R (343P)"<the...@jp...> >>> >>> Subject: Re: [Matplotlib-users] [ploting data] Live data >>> >>> Perhaps I'm missing something, but why not use QTimer? You can't really >>> every call sleep in a single threaded gui (for reasons you've encountered). >>> If you need to poll something, create a QTimer for 2 seconds and have it >>> call a measurement function to update the data. You shouldn't need any >>> processEvents calls or sleep. >> |