Reputation: 327
I've been working on this code tirelessly throughout the day, but can't seem to figure out where my logic is off. I want the user to be able to browse for a file (here they are simply pressing a button called 'Browse') that immediately updates the shown plot (here going from blue lines to red in the plot; but ultimately in my actual program going from a blank plot to a filled one, or from a filled to a different filled one).
It's inspired by an example from https://matplotlib.org/examples/user_interfaces/embedding_in_qt5.html, but I've altered it quite a bit to express my current problem in a way that is most hopefully minimal and complete. Thank you so much in advance for even taking a look.
import sys
import os
import random
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QGridLayout, QFileDialog, QPushButton
from numpy import arange
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
"""A canvas that updates itself every second with a new plot."""
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
#timer = QtCore.QTimer(self)
#timer.timeout.connect(self.update_figure)
#timer.start(1000)
def compute_initial_figure(self):
self.axes.plot([0, 1, 2, 3], [1, 2, 0, 4], 'b')
def update_figure(self):
print('update')
# Build a list of 4 random integers between 0 and 10 (both inclusive)
l = [random.randint(0, 10) for i in range(4)]
self.axes.cla()
if P1.df is True:
self.axes.plot(P1.df, l, 'r') #should change to red, but doesn't
else:
self.axes.plot([0, 1, 2, 3], l, 'b')
self.draw()
class P1(QtWidgets.QWidget):
df = False #datafile is originally empty
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QGridLayout(self)
self.button_browse = QPushButton('Browse', self)
self.button_browse.clicked.connect(self.browseFile)
layout.addWidget(self.button_browse, 1, 1, 1, 1)
self.button_browse.show()
dc = MyDynamicMplCanvas(self, width=5, height=4, dpi=100)
layout.addWidget(dc, 2, 1, 1, 1)
def browseFile(self): #user presses browse to load new datafile
print(P1.df)
P1.df = [0, 1, 2, 3]
print(P1.df)
#loading new datafile needs to update plot:
MyDynamicMplCanvas().update_figure()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.stack = QtWidgets.QStackedWidget(self)
P1f = P1(self)
self.stack.addWidget(P1f)
self.setCentralWidget(self.stack)
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
aw = MainWindow()
aw.show()
sys.exit(qApp.exec_())
Upvotes: 0
Views: 208
Reputation: 244043
You have 2 errors:
When using MyDynamicMplCanvas().update_figure()
you are creating a new MyDynamicMplCanvas()
object that is different from dc = MyDynamicMplCanvas(self, width = 5, height = 4, dpi = 100)
, so being a local variable is eliminated a never shown.
The second is that the sentence P1.df
is True will never be true since P1.df
is False or is a list.
The solution is to make a member of the class and changes if P1.df is True:
to if P1.df:
class MyDynamicMplCanvas(MyMplCanvas):
...
def update_figure(self):
print('update')
# Build a list of 4 random integers between 0 and 10 (both inclusive)
l = [random.randint(0, 10) for i in range(4)]
self.axes.cla()
if P1.df:
self.axes.plot(P1.df, l, 'r') #should change to red, but doesn't
else:
self.axes.plot([0, 1, 2, 3], l, 'b')
self.draw()
class P1(QtWidgets.QWidget):
df = False
def __init__(self, parent=None):
...
self.dc = MyDynamicMplCanvas(self, width=5, height=4, dpi=100)
layout.addWidget(self.dc, 2, 1, 1, 1)
def browseFile(self): #user presses browse to load new datafile
P1.df = [0, 1, 2, 3]
#loading new datafile needs to update plot:
self.dc.update_figure()
...
Upvotes: 1