How do you run Matplotlib in anothor thread on PyQt

I need to display some charts in my PyQt application, so I write down these code. It is works, but sometimes, draw a chart will spend a lot of time, it will "freeze" the main window.

I think do it in another thread should resolved it. But how can I do it? Or, there is another way to draw a chart in "non-block" mode?

from PyQt4 import QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas   
from matplotlib.figure import Figure

class MplCanvas(FigureCanvas):

    def __init__(self):
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)

        # do something...
        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        # do something...

    def draw(self):
        # do something...

Answers


The basics of Python threading for simple uses like this are really easy.

You'll need to

import threading

and then, instead of just calling x.draw(), create a thread and run it as follows:

draw_thread = threading.Thread(target=x.draw)
draw_thread.start()

That will probably get you 90% of the way at least. You can read the docs to detect things like still-running threads, waiting for threads, and so on. But at heart, it's not difficult and if ti's just simple interactive graphics this might even suffice.

Be aware, though, that if draw() references globals, there is the potential for race conditions to occur,making your program unreliable. This is a further advantage of writing code with good coupling, clean interfaces and no references to mutable globals (unless locking is used to protect those resources).


You should us QThreads in your Qt application (to make the frame work do all of the hard work for you)

  1. put your time consuming work in a worker class (that is derived from QObject)

  2. In you class that is caling the plotting add something like

    self.thread = QtCore.QThread(parent=self)
    
    self.worker = Worker(parent=None)
    self.worker.moveToThread(self.thread)
    self.thread.start()
    

and communicate with your worker via signals/slots. If you call it directly (as in self.worker.do_slow_stuff()), it will run on the thread you call it from, which will block the main event loop making the interface freeze.

A good explanation of how to (and not to) do threading with QThread (read both..the first one now describes the default behaviour)


Need Your Help

Accessing environment variables in Javascript on Heroku?

javascript ruby heroku environment-variables rack

I have a ruby/rack app on Heroku serving a site. The site uses Javascript and I want to access an Heroku environment variable in the Javascript file (an API key). I've tried:

How I can make the eyeballs following the cursor move?

c# .net

I have created two circles as eyes and two eye balls in it. I want to move these eyeballs with the cursor move. What should i do?

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.