Reputation: 149
I had a question yesterday about how to update an embedded matplotlib plot in a pyqt5 gui with toolbar which works fine now. But in my application it is more complex compared to the minimal example.
I have a class that is doing the analysis and creating plots via matplotlib while the GUI is in a separated class in another file. I made a modified minimal example:
# -*- coding: utf-8 -*-
import sys
import numpy as np
from PyQt5 import QtCore, QtWidgets, uic
import matplotlib
matplotlib.use('QT5Agg')
import matplotlib.pylab as plt
from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvas, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class Analysis():
def __init__(self):
self.fig, self.ax1 = plt.subplots()
bins = np.arange(0.1, 2, 0.02)
data = np.random.rand(3,2)
self.ax1.hist(data, bins, alpha=0.6, density=False, cumulative=False)
def getAxis(self):
return self.ax1
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
uic.loadUi('test.ui', self)
# default data
data = np.array([0.7,0.7,0.7,0.8,0.9,0.9,1.5,1.5,1.5,1.5])
self.fig, self.ax1 = plt.subplots()
bins = np.arange(0.1, 2, 0.02)
n1, bins1, patches1 = self.ax1.hist(data, bins, alpha=0.6, density=False, cumulative=False)
# plot
self.plotWidget = FigureCanvas(self.fig)
self.lay = QtWidgets.QVBoxLayout(self.content_plot)
self.lay.setContentsMargins(0, 0, 0, 0)
self.lay.addWidget(self.plotWidget)
# add toolbar
self.addToolBar(QtCore.Qt.BottomToolBarArea, NavigationToolbar(self.plotWidget, self))
# button event
self.pushButton.clicked.connect(self.update)
# show window
self.show()
#############################################
def update(self):
# clear local axis
self.ax1.cla()
# get axis from analysis object
a = Analysis()
ax = a.getAxis()
# ???????????
self.ax1 = ax
# draw the new content
self.fig.canvas.draw_idle()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
sys.exit(app.exec_())
The idea is to create a matplotlib object in the Analysis class and to store the axes of the results to get them in another method to plot it on an embedded PyQt5 widget.
But my code doesn't work. It cleans the local axes but it doesn't set the axes from the Analysis object. How can I do that correctly?
Thanks!
Upvotes: 1
Views: 554
Reputation: 40667
You are creating a new figure and axes in your class Analysis
. You cannot take one axes from one figure and put it in another figure just like that. Instead, design your Analysis
class so it takes an Axes object at initialization.
You may want to read matplotlib's coding style document.
class Analysis():
def __init__(self, ax=None):
if ax is None:
ax = plt.gca()
bins = np.arange(0.1, 2, 0.02)
data = np.random.rand(3,2)
ax.hist(data, bins, alpha=0.6, density=False, cumulative=False)
(...)
def update(self):
# clear local axis
self.ax1.cla()
a = Analysis(ax=self.ax1)
self.fig.canvas.draw_idle()
Upvotes: 3