Reputation: 771
I am trying to make a dynamic chart where the patches are updated when the user moves a slider. I am using the matplotlib and pyqt packages that came with anaconda python. The code i have runs and does the drawing properly once but when I move the slider the update fails.
I have the following
my layout is created with the following class
class plotArea(QtGui.QWidget):
def __init__(self):
super(plotArea, self).__init__()
self.init()
def init(self):
grid = QtGui.QGridLayout()
self.setLayout(grid)
title = QtGui.QLabel('Title')
sldTime = QtGui.QSlider(QtCore.Qt.Horizontal)
sldLevel = QtGui.QSlider(QtCore.Qt.Vertical)
plot = MyDynamicMplCanvas()
sldTime.valueChanged[int].connect(plot.changeValue)
sldLevel.valueChanged[int].connect(plot.changeValue)
grid.addWidget(title, 0, 0, 1, 10)
grid.addWidget(sldLevel, 1, 0, 10, 1)
grid.addWidget(sldTime, 11, 1, 1, 9)
grid.addWidget(plot, 1, 1, 9, 9)
my chart class with the drawing and update method are shown below
class MyDynamicMplCanvas(FigureCanvas):
"""A canvas that updates itself every second with a new plot."""
def __init__(self):
fig = Figure()
FigureCanvas.__init__(self, fig)
chart = fig.add_subplot(111)
chart.set_xlim([0, 4])
chart.set_ylim([0, 4])
self.draw_lattice(chart)
def draw_lattice(self, chart):
min_val = 0
max_val = 100
my_cmap = cm.get_cmap('jet')
norm = matplotlib.colors.Normalize(min_val, max_val)
color_i = my_cmap(norm(np.random.uniform(0, 100)))
my_cmap = cm.get_cmap('jet')
square = Rectangle((1, 1), 1, 1, alpha=0.5, facecolor=color_i,
edgecolor='k')
chart.add_patch(square)
def changeValue(self,chart):
self.draw_lattice(chart)
Since both methods are in the same class there shouldnt be any scoping issues and the code does work on the initial pass but gives the following error if I move the slider.
chart.add_patch(square)
AttributeError: 'int' object has no attribute 'add_patch'
I have been struggling with this for a bit what am i doing wrong? Do I need to delete the subplot? I am not sure why calling from changeValue causes the code to fail. Any help is much appreciated.
Upvotes: 1
Views: 579
Reputation: 5659
Even though you define chart in the init method, you don't actually keep a reference to it. To actually keep it you need to turn the line
chart = fig.add_subplot(111)
to
self.chart = fig.add_subplot(111)
then reference it using self.chart
.
You are passing an integer into your slot, which will be the chart
argument when the signal is generated, which is why you get that int
error - chart
is treated as an Axes object in the code, but any events will put an integer into that variable. I would change the input to your slot to be the slidervalue, and just reference self.chart
to update your plot.
Upvotes: 1