Hi David, I'm sorry to answer so late. I was in Holyday. I've changed the program according to your remarks. It works fine! I have only one problem. I want to start the new thread when I clik on a QPushButton but If I just remove
thread = AThread() thread.start() from if __name__ == "__main__": qApp = QtGui.QApplication([" "]) aw = ApplicationWindow() aw.showMaximized() thread = AThread() thread.start() sys.exit(qApp.exec_()) and I create a single button : def demarrer(self): thread = AThread() thread.start() The program crashes and "say": QThread: Destroyed while thread is still running Do you have any idea? Thanks again! Fabien 2012/12/21 David Hoese <dho...@gmail.com> > Hey Fabien, > > See comments below and the bottom for my final changes. Please CC me in > replies. > > On 12/21/12 5:06 AM, lafont.fab...@gmail.com wrote: > > Hello everyone, > > I'm trying to plot live datas using matplotlib and PyQt. I need a > multithreaded program beacause I use time.sleep and it freeze completely > the app during that moment. I've tried that but it crash immediatly: > > > Do you get a seg. fault or some other error? I'm pretty sure I've helped > you with this type of Qt application before, but I'll see what I can clear > up. > > from PyQt4 import QtCore, QtGui > > import time > > import sys > > from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as > FigureCanvas > > from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as > NavigationToolbar > > from matplotlib.figure import Figure > > # Subclassing QThread > > # http://doc.qt.nokia.com/latest/qthread.html > > class Graph(FigureCanvas): > > def __init__(self,parent): > > self.fig = Figure() > self.ax = self.fig.add_subplot(111) > > FigureCanvas.__init__(self, self.fig) > > self.R1 = [] > > self.l_R1, = self.ax.plot([], self.R1,"-o") > > self.fig.canvas.draw() > > FigureCanvas.updateGeometry(self) > > class ApplicationWindow(QtGui.QMainWindow): > > """Example main window""" > > def __init__(self): > > QtGui.QMainWindow.__init__(self) > > self.main_widget = QtGui.QWidget(self) > > vbl = QtGui.QGridLayout(self.main_widget) > > qmc = Graph(self.main_widget) > > vbl.addWidget(qmc,0,0,1,11) > > self.setCentralWidget(self.main_widget) > > First, a small thing, I'm not sure if this matters but I've always > created layouts by doing: > > vbl = QtGui.QGridLayout() > # addWidget > self.main_widget.setLayout(vbl) > > I got this pattern from the documentation: > > http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwidget.html#setLayout > > > class AThread(QtCore.QThread): > > def run(self): > > count = 0 > > while count < 5: > > time.sleep(1) > > print "Increasing" > > count += 1 > > aw.l_R1.set_data(count, count) > > I don't approve of subclassing the "run" method of QThread, but what you > have should work a little bit for now. I really don't approve of using a > global in another thread affinity and I highly doubt this will work > correctly. You should be using Qt signals to communicate between threads, > but using signals you may have to get a little more complex with how you > are using QThreads to free up the event loops. > > You are also calling "aw.l_R1" which does not exist. You need to have a > way to access the graph. As a quick hack I just set the graph to > "self.qmc" and then in the run method I did "aw.qmc.l_R1.set_data(count, > count)". You will also want to update the limits to show the new data as > it comes in or set it to a certain range from the start. You will need to > redraw the canvas every time you update it. You will likely run into > problems in the future if you draw in a different thread from the GUI > thread, but for some reason it works in your example. > > I'm not sure if this was intended, but since you are not saving the > previous "count" you are only plotting points not a line. One way to do > this is if you want to keep the last N records (lets say N=200) then you > can plot originally "self.ax.plot(numpy.arange(200), numpy.zeros(200))" and > then update the y-data only like this "aw.qmc.set_ydata(<length 200 array > of previous counts>)". > > > def usingQThread(): > > app = QtCore.QCoreApplication([]) > > thread = AThread() > > thread.finished.connect(app.exit) > > thread.start() > > sys.exit(app.exec_()) > > I'm really confused at this point. How have you been calling this > module? As "python test.py"? You are creating 2 QApplications, which isn't > the easiest to follow. You should create 1 application, then make the > window, then make the threads. > > Another big thing is that when you run "thread.finished.connect(app.exit)" > you are connecting the end of the thread to the app closing. Do you want > the Application to completely close when the thread finishes (as you have > it which I've never done so not sure if this will cause problems in more > complex applications) or do you want the thread to stop, leaving the window > open? The application would then close when the last window is closed. > > > if __name__ == "__main__": > > # > > qApp = QtGui.QApplication(sys.argv) > > aw = ApplicationWindow() > > aw.showMaximized() > > usingQThread() > > sys.exit(qApp.exec_()) > > > I removed "usingQThread" method and moved that logic to the if statement > so it now looks like this: > > if __name__ == "__main__": > qApp = QtGui.QApplication([" "]) > aw = ApplicationWindow() > aw.showMaximized() > thread = AThread() > thread.finished.connect(qApp.exit) > thread.start() > sys.exit(qApp.exec_()) > > > I also added a "self.qmc = qmc" in the ApplicationWindow and forced the > y-limits in the Graph.__init__ method using the following: > > self.ax.set_xlim(-1, 6) > self.ax.set_ylim(-1, 6) > > Then in the run method the last 2 lines in the while loop now say: > > aw.qmc.l_R1.set_data(count, count) > aw.qmc.draw() > > > This got it running for me, although it had the plotting points problem I > mentioned earlier. Hopefully this will get you somewhere. But I can not > stress enough that you need to research QThreads and how they should be > used correctly and how threads work in general. As I noted above you > should not be drawing in non-GUI threads and you should not be magically > using a global variable that lives in another thread (use signals and > slots). This is bad practice and will likely lead to obscure errors and a > lot of headache when you're short on time (assuming this is for a work > project like mine was). > > Good luck. > > -Dave > >
_______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt