When I run my setup_plot
and dataq
functions on their own the pyplot window behaves as expected, i.e. after the run finishes the buttons (pan/zoom etc) in the navigation toolbar are active. However, when I import the functions and call them from a button event handler in my main program the pyplot window stays active after the run finishes: it is still accepting data and the toolbar buttons are inactive. How should I stop plotting without closing the plot window? Here is a snippet:
class MyWindowClass(QtGui.QWidget, form_class):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.pushButton_Run.clicked.connect(self.pushbutton_run_clicked)
self.pushButton_Stop.clicked.connect(self.pushbutton_stop_clicked)
def pushbutton_run_clicked(self):
# get line edit values here
functions.setup_plot()
functions.dataq(steptime, runtime, CO2_1, CO2_2)
I tried to reproduce your problem by creating a simple MCVE based on the code snippet you gave us. The only thing I could find that would make my simple application to behave as you described is if I do not set the backend
of matplotlib to Qt4Agg
.
from PyQt4 import QtGui
import sys
import numpy as np
import matplotlib as mpl
mpl.use('Qt4Agg')
import matplotlib.pyplot as plt
class MyWindowClass(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindowClass, self).__init__(parent)
pushButton_Run = QtGui.QPushButton('Run')
pushButton_Run.clicked.connect(self.pushbutton_run_clicked)
layout = QtGui.QGridLayout()
layout.addWidget(pushButton_Run, 0, 0)
self.setLayout(layout)
def pushbutton_run_clicked(self):
fig, ax = setup_plot()
dataq(fig, ax)
def setup_plot():
fig, ax = plt.subplots()
fig.canvas.manager.show()
return fig, ax
def dataq(fig, ax):
for i in range(200):
ax.plot(np.random.rand(1), np.random.rand(1), 'o')
fig.canvas.draw()
fig.canvas.flush_events()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mywindow = MyWindowClass()
mywindow.show()
sys.exit(app.exec_())
This is another way to setup your artists that may allow you to more easily used them within multiple functions and can make their manipulation more convenient.
from PyQt4 import QtGui
import sys
import numpy as np
import matplotlib as mpl
mpl.use('Qt4Agg')
import matplotlib.pyplot as plt
class MyWindowClass(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindowClass, self).__init__(parent)
#---- generate some data ----
self.x = np.random.rand(50)
self.y = np.random.rand(50)
#---- create a layout ----
pushButton_Run = QtGui.QPushButton('Run')
pushButton_Run.clicked.connect(self.pushbutton_run_clicked)
pushButton_Clear = QtGui.QPushButton('Clear')
pushButton_Clear.clicked.connect(self.clear_plot)
layout = QtGui.QGridLayout()
layout.addWidget(pushButton_Run, 0, 0)
layout.addWidget(pushButton_Clear, 1, 0)
self.setLayout(layout)
#---- init artists ----
self.fig, self.ax = plt.subplots()
self.fig.canvas.manager.show()
def clear_plot(self):
self.ax.cla()
self.fig.canvas.draw()
self.fig.canvas.flush_events()
def pushbutton_run_clicked(self):
self.setEnabled(False)
self.ax.cla()
dataq(self.fig, self.ax, self.x, self.y)
dataq2(self.fig, self.ax, self.x, self.y)
self.setEnabled(True)
def dataq(fig, ax, x, y):
for i in range(len(x)):
ax.plot(x[i], y[i], 'o')
fig.canvas.draw()
fig.canvas.flush_events()
def dataq2(fig, ax, x, y):
for i in range(len(x)-1):
ax.plot(x[i:i+2], y[i:i+2], '-')
fig.canvas.draw()
fig.canvas.flush_events()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mywindow = MyWindowClass()
mywindow.show()
sys.exit(app.exec_())