1

So I'd like to integrate a matplotlib canvas in qt5 with manual blit. I've found this thread: Fast Live Plotting in Matplotlib / PyPlot and the voted answer seems pretty nice however I need it in a qt5 window...

So I have tried to mash the code above together with the matplotlib qt5 tutorial into one script. https://matplotlib.org/gallery/user_interfaces/embedding_in_qt5_sgskip.html It kinda works, however the animation only works when using the pan/zoom and the background is black :D and if blit is set to false it doesnt even draw...

If somebody could help me that would be amazing :) Its hilariously broken

from __future__ import unicode_literals
import random
import time
import matplotlib
from PyQt5.QtWidgets import QSizePolicy, QApplication, QWidget, QVBoxLayout
from matplotlib import pyplot as plt
import sys
import matplotlib
matplotlib.use('Qt5Agg')

from matplotlib.animation import FuncAnimation
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import numpy as np


class MyMplCanvas(FigureCanvas):
    # Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.).
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = plt.figure()

        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                                   QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

        self.x = np.linspace(0, 50., num=100)
        self.X, self.Y = np.meshgrid(self.x, self.x)
        # self.fig = plt.figure()
        self.ax1 = self.fig.add_subplot(2, 1, 1)
        self.ax2 = self.fig.add_subplot(2, 1, 2)

        self.img = self.ax1.imshow(self.X, vmin=-1, vmax=1, interpolation="None", cmap="RdBu")

        self.line, = self.ax2.plot([], lw=3)
        self.text = self.ax2.text(0.8, 0.5, "")

        self.ax2.set_xlim(self.x.min(), self.x.max())
        self.ax2.set_ylim([-1.1, 1.1])

        self.t_start = time.time()
        self.k = 0.

        #self.fig.canvas.draw()  # note that the first draw comes before setting data

        #self.update(blit=False)
        anim = FuncAnimation(self.fig, self.update, interval=20)

    def update(self, blit=True):
        if blit:
            # cache the background
            self.axbackground = self.fig.canvas.copy_from_bbox(self.ax1.bbox)
            self.ax2background = self.fig.canvas.copy_from_bbox(self.ax2.bbox)


        self.img.set_data(np.sin(self.X / 3. + self.k) * np.cos(self.Y / 3. + self.k))
        self.line.set_data(self.x, np.sin(self.x / 3. + self.k))
        self.k += 0.11
        if blit:
            # restore background
            self.fig.canvas.restore_region(self.axbackground)
            self.fig.canvas.restore_region(self.ax2background)

            # redraw just the points
            self.ax1.draw_artist(self.img)
            self.ax2.draw_artist(self.line)
            self.ax2.draw_artist(self.text)

            # fill in the axes rectangle
            self.fig.canvas.blit(self.ax1.bbox)
            self.fig.canvas.blit(self.ax2.bbox)

            # in this post http://bastibe.de/2013-05-30-speeding-up-matplotlib.html
            # it is mentionned that blit causes strong memory leakage.
            # however, I did not observe that.

        else:
            # redraw everything
            self.fig.canvas.draw()

            # self.fig.canvas.flush_events()
            # alternatively you could use
            # plt.pause(0.000000000001)
            # however plt.pause calls canvas.draw(), as can be read here:
            # http://bastibe.de/2013-05-30-speeding-up-matplotlib.html


class PlotDialog(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.plot_layout = QVBoxLayout(self)
        self.plot_canvas = MyMplCanvas(self, width=5, height=4, dpi=100)

        self.navi_toolbar = NavigationToolbar(self.plot_canvas, self)
        self.plot_layout.addWidget(self.plot_canvas)
        self.plot_layout.addWidget(self.navi_toolbar)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    dialog0 = PlotDialog()
    dialog0.show()
    sys.exit(app.exec_())

Blissed
  • 11
  • 2

0 Answers0