<div dir="ltr"><div><div><div><div><div><div>Hi David, I'm sorry to answer so late. I was in Holyday.<br><br></div>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 <br>
<br>    thread = AThread()<br>    thread.start()<br><br></div>from <br><br>if __name__ == "__main__":<br>    qApp = QtGui.QApplication([" "])<br>    aw = ApplicationWindow()<br>    aw.showMaximized()<br>
    thread = AThread()<br>    thread.start()<br>    sys.exit(qApp.exec_())<br><br><br></div>and I create a single button :<br><br>def demarrer(self):<br>       thread = AThread()<br>      thread.start()<br><br><br></div>The program crashes and "say":    QThread: Destroyed while thread is still running<br>
<br><br></div>Do you have any idea?<br><br></div>Thanks again!<br><br>Fabien<br><div><div><div><div><div><br></div></div></div></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">2012/12/21 David Hoese <span dir="ltr"><<a href="mailto:dhoese@gmail.com" target="_blank">dhoese@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <div>
      <div>Hey Fabien,<br>
        <br>
        See comments below and the bottom for my final changes. Please
        CC me in replies.<br>
      </div><div class="im">
      <br>
      On 12/21/12 5:06 AM, <a href="mailto:lafont.fabien@gmail.com" target="_blank">lafont.fabien@gmail.com</a> wrote:<br>
    </div></div><div class="im">
    <blockquote type="cite">
      <pre>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:

</pre>
    </blockquote></div>
    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.
    <div><div class="h5"><blockquote type="cite">
      <pre>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

# <a href="http://doc.qt.nokia.com/latest/qthread.html" target="_blank">http://doc.qt.nokia.com/latest/qthread.html</a>

class Graph(FigureCanvas):

def __init__(self,parent):

self.fig = Figure()

<a href="http://self.ax" target="_blank">self.ax</a> = 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)</pre>
    </blockquote></div></div>
    First, a small thing, I'm not sure if this matters but I've always
    created layouts by doing:<br>
    <br>
    <blockquote><tt>vbl = QtGui.QGridLayout()</tt><tt><br>
      </tt><tt># addWidget</tt><tt><br>
      </tt><tt>self.main_widget.setLayout(vbl)</tt><tt><br>
      </tt></blockquote>
    I got this pattern from the documentation:<br>
<a href="http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwidget.html#setLayout" target="_blank">http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwidget.html#setLayout</a><div class="im">
    <blockquote type="cite">
      <pre>
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)</pre>
    </blockquote></div>
    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.<br>
    <br>
    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.<br>
    <br>
    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>)".<div class="im"><br>
    <blockquote type="cite">
      <pre>
def usingQThread():

app = QtCore.QCoreApplication([])

thread = AThread()

thread.finished.connect(app.exit)

thread.start()

sys.exit(app.exec_())</pre>
    </blockquote></div>
    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.<br>
    <br>
    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.
    <div class="im"><blockquote type="cite">
      <pre>
if __name__ == "__main__":

#

 qApp = QtGui.QApplication(sys.argv)

aw = ApplicationWindow()

aw.showMaximized()

usingQThread()

sys.exit(qApp.exec_())

</pre>
    </blockquote></div>
    I removed "usingQThread" method and moved that logic to the if
    statement so it now looks like this:<br>
    <br>
    <blockquote><tt>if __name__ == "__main__":</tt><tt><br>
      </tt><tt>    qApp = QtGui.QApplication([" "])</tt><tt><br>
      </tt><tt>    aw = ApplicationWindow()</tt><tt><br>
      </tt><tt>    aw.showMaximized()</tt><tt><br>
      </tt><tt>    thread = AThread()</tt><tt><br>
      </tt><tt>    thread.finished.connect(qApp.exit)</tt><tt><br>
      </tt><tt>    thread.start()</tt><tt><br>
      </tt><tt>    sys.exit(qApp.exec_())</tt><tt><br>
      </tt></blockquote>
    <br>
    I also added a "self.qmc = qmc" in the ApplicationWindow and forced
    the y-limits in the Graph.__init__ method using the following:<br>
    <br>
    <blockquote><tt>self.ax.set_xlim(-1, 6)</tt><tt><br>
      </tt><tt>self.ax.set_ylim(-1, 6)</tt><tt><br>
      </tt></blockquote>
    Then in the run method the last 2 lines in the while loop now say:<br>
    <br>
    <blockquote><tt> aw.qmc.l_R1.set_data(count, count)</tt><tt><br>
      </tt><tt> aw.qmc.draw()</tt><tt><br>
      </tt></blockquote>
    <br>
    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).<br>
    <br>
    Good luck.<br>
    <br>
    -Dave<br>
    <br>
  </div>

</blockquote></div><br></div>