Take the 2-minute tour ×

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)
        # do something...

    def draw(self):
        # do something...
share|improve this question
add comment

2 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)

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).

share|improve this answer
add comment

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)

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)

share|improve this answer
add comment

Your Answer


