How to run Matplotlib in another thread in PyQt
I need to display some diagrams in my PyQt application, so I am writing this code. This works, but sometimes drawing the diagram will take a lot of time, it will "freeze" the main window.
I think doing it in a different thread should have solved. But how can I do this? Or is there another way to draw the diagram in "non-blocking" 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...
source to share
You have to QThreads
in your application Qt
(to make the frame work, do all the hard work for you)
-
put your laborious work in the working class (derived from
QObject
) -
In your class that frames the graphics add something like
self.thread = QtCore.QThread(parent=self) self.worker = Worker(parent=None) self.worker.moveToThread(self.thread) self.thread.start()
and exchange information with your worker through signals / slots. If you call it directly (as in self.worker.do_slow_stuff()
), it will run on the thread from which you call it, which blocks the main event loop, causing the interface to freeze.
Nice explanation on how (and not ) to stream with QThread
(read both: the first describes the default behavior)
source to share
The basics of Python streaming for easy use like this is very simple.
You need
import threading
and then instead of just calling x.draw () create a stream and run it like this:
draw_thread = threading.Thread(target=x.draw) draw_thread.start()
You will probably get at least 90% of the way. You can read the docs to spot things like still threads, waiting threads, etc. But deep down it's not hard, and if it's just simple interactive graphics, it might even be enough.
Remember, however, that if draw () refers to globals, there is a possibility of race conditions, which makes your program unreliable. This is another advantage of writing code with good cohesion, clean interfaces, and no reference to mutable globals (unless locking is used to protect those resources).
source to share