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

      

+3


source to share


2 answers


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)

+2


source


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

+1


source







All Articles