I have a written a large data processing and plotting application using PyQt5 with Matplotlib and I am plagued by old plots reappearing when creating new ones. I have seen many questions answered regarding this but none of the suggested methods work for me.
I have reduced the problem down to the following simplified code:
from PyQt5.QtWidgets import (QApplication, QMainWindow, QDialog, QPushButton,
QVBoxLayout, QGroupBox)
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import sys
class PlotCanvas(FigureCanvas):
""" Subclass of the MPL FigureCanvas class. """
def __init__(self, parent=None):
self.parent = parent
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
self.fig.set_tight_layout(True)
FigureCanvas.__init__(self, self.fig)
class PlotWindow(QDialog):
""" Create plot in window and plot supplied data. """
def __init__(self, parent, x, y):
super().__init__()
self.parent = parent
self.x = x
self.y = y
self.set_up_gui()
self.l2d = self.canvas.ax.plot(self.x, self.y)[0]
def set_up_gui(self):
""" Create GUI. """
vbl = QVBoxLayout()
self.canvas = PlotCanvas(self)
vbl.addWidget(self.canvas)
self.setLayout(vbl)
def closeEvent(self, event):
""" Delete figure on closing window. """
plt.close(self.canvas.fig)
super(PlotWindow, self).closeEvent(event)
class MainApp(QMainWindow):
""" My main application class """
def __init__(self, parent=None):
super(QMainWindow, self).__init__()
# Create some arbitrary data
self.x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.y = [2, 4, 6, 4, 2, 4, 6, 8, 6]
self.set_up_gui()
def set_up_gui(self):
""" Create GUI with 2 buttons for creating 2 plots. """
btn1 = QPushButton()
btn1.setText('Button 1')
btn1.clicked.connect(self.plot1)
btn2 = QPushButton()
btn2.setText('Button 2')
btn2.clicked.connect(self.plot2)
vbl = QVBoxLayout()
vbl.addWidget(btn1)
vbl.addWidget(btn2)
gb = QGroupBox()
gb.setLayout(vbl)
self.setCentralWidget(gb)
def plot1(self):
""" Plot using my PlotWindow class. """
p = PlotWindow(self, self.x, self.y)
p.show()
def plot2(self):
""" Plot using regular MPL plot call. """
fig = plt.figure()
plt.plot([10, 20, 30], [4, 8, 2])
plt.show()
plt.close(fig)
if __name__=='__main__':
app = QApplication(sys.argv)
main = MainApp()
main.show()
sys.exit(app.exec_())
The odd behavior is this:
- Press button 1, plot 1 appears, press red X to close window.
- Press button 2, plot 2 appears, press red X to close window.
- Press button 1, plot 1 appears, press red X to close window.
- Press button 2, plot 2 appears but so does plot 1, press red X to close plot 2, plot 1 also closes.
- From here on, button 1 brings up plot 1, and button 2 brings up both plots.
Based on answers to similar questions (such as matplotlib.pyplot will not forget previous plots - how can I flush/refresh?), I have tried various things, such as following plt.show()
with plt.cla()
plt.clf()
and plt.close()
but none of them fix the problem. As you can see in my code, I have added the the plt.close()
to the PyQt5 window close event and also the regular MPL plot but this seems to do nothing.
EDIT: Now that the question is answered, I have cleaned up some of the musings that followed and reduced it to the pertinent information.
I tried this code out on my work Linux machine (originally developed on Mac) and don't get the same double plot behavior. Which shows it's platform-dependent.
On Linux I can actually remove the plt.close()
from the plot2 method and I can remove the closeEvent
method from the PlotWindow
class and it works fine without any double plots showing.