unable to update matplotlib figure in pyqt5
-
wrote on 13 Feb 2023, 17:32 last edited by
I am studying MDIwindow in pyqt5 I want to update the ForcemapWidget figure when I click on the HeatmapWidget figure. However, the diagram did not update. It is confirmed that the canvas in the ForcemapWidget is updated by the print function. We know that the coordinates are also obtained. But for some reason, the chart doesn't update.
import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) bar=self.menuBar () file=bar.addMenu ("File") file.addAction ("New") file.addAction ("Cascade") file.addAction ("Tiled") file.triggered[QAction].connect (self.tritri) self.setWindowTitle ("MDI Application") # 最初のサブウィンドウを作成 sub=QMdiSubWindow () form_widget=FormWidget () sub.setWidget (form_widget) sub.setWindowTitle ("Sub Window 1") self.mdi.addSubWindow (sub) sub.show () sub2=QMdiSubWindow () # ForcemapWidget.force_update () form_widget=ForcemapWidget () # form_widget.update() # print(form_widget) sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show() def tritri(self,p): if p.text ()=="New": MDIWindow.count=MDIWindow.count+1 sub=QMdiSubWindow () heatmap_widget=HeatmapWidget () sub.setWidget (heatmap_widget) sub.setWindowTitle ("Sub Window"+str (MDIWindow.count)) self.mdi.addSubWindow (sub) sub.show () if p.text ()=="Cascade": self.mdi.cascadeSubWindows () if p.text ()=="Tiled": self.mdi.tileSubWindows () class HeatmapWidget(QWidget): def __init__(self): super().__init__() self.forcemapWidget=ForcemapWidget fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def onclick(self,event): x,y=event.xdata,event.ydata forcemap=ForcemapWidget (x) class ForcemapWidget (QWidget): def __init__(self,x=None): super ().__init__ () self.figure=plt.figure () self.initUI (x) def initUI(self,x): self.figure.clear () ax=self.figure.add_subplot (111) if x is not None: heatmap=np.random.rand (int (x),256) else: heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") # self.figure.colorbar (im) canvas=FigureCanvas (self.figure) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) self.update () # def abc(self,x): # self.x=x # print(x) class FormWidget(QWidget): def __init__(self): super().__init__() form_layout = QFormLayout() combo = QComboBox() combo.addItems(["Option 1", "Option 2", "Option 3"]) form_layout.addRow("Dropdown:", combo) line_edit = QLineEdit() form_layout.addRow("Input:", line_edit) button = QPushButton("Submit") form_layout.addRow(button) check_box = QCheckBox() form_layout.addRow("Checkbox:", check_box) self.setLayout(form_layout) app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
-
@SGaist
I made one that updates the color when clicked, but it doesn't.
Do you know why?import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) self.setWindowTitle ("MDI Application") sub2=QMdiSubWindow () form_widget=ForcemapWidget () sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show() sub3=QMdiSubWindow () form_widget=HeatmapWidget () sub3.setWidget (form_widget) sub3.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub3) sub3.show() class HeatmapWidget(QWidget): def __init__(self,parent=None): super().__init__() # self.forcemapWidget=ForcemapWidget() fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def onclick(self, event): self.force=ForcemapWidget() self.force.updates() class ForcemapWidget(QWidget): def __init__(self): super().__init__() self.figure = plt.figure(figsize=(5, 4)) ax = self.figure.add_subplot(111) heatmap = np.random.rand(256, 256) self.im = ax.imshow(heatmap, cmap="Oranges") self.colorbar = self.figure.colorbar(self.im) canvas = FigureCanvas(self.figure) layout = QVBoxLayout() layout.addWidget(canvas) self.setLayout(layout) def updates(self): self.im.set_cmap("Blues") self.figure.canvas.draw() app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
wrote on 15 Feb 2023, 01:57 last edited byI understand this.
Here is the code as an example.import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) self.setWindowTitle ("MDI Application") sub2=QMdiSubWindow () form_widget=ForcemapWidget () sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show () sub3 = QMdiSubWindow() form_widget = HeatmapWidget(forcemap_widget=form_widget) sub3.setWidget(form_widget) sub3.setWindowTitle("Sub Window 3") self.mdi.addSubWindow(sub3) sub3.show() class HeatmapWidget(QWidget): def __init__(self, forcemap_widget, parent=None): super().__init__() self.forcemap_widget = forcemap_widget fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) self.canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (self.canvas) self.setLayout (layout) def onclick(self, event): x, y = event.xdata, event.ydata self.forcemap_widget.updates() # 正 class ForcemapWidget(QWidget): def __init__(self): super().__init__() self.figure = plt.figure(figsize=(5, 4)) ax = self.figure.add_subplot(111) heatmap = np.random.rand(256, 256) self.im = ax.imshow(heatmap, cmap="Oranges") self.colorbar = self.figure.colorbar(self.im) self.canvas = FigureCanvas(self.figure) layout = QVBoxLayout() layout.addWidget(self.canvas) self.setLayout(layout) def updates(self): self.im.set_cmap("Blues") self.figure.canvas.draw() # self.show() app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
-
Hi and welcome to devnet,
If you are talking about the onclick method of HeatmapWidget, it just creates a local variable of type ForcemapWidget so I am unsure about what you expect there.
-
wrote on 13 Feb 2023, 20:01 last edited by
thank you for your reply.
I want to get coordinates on click of HeatmapWidget and change dimension of ForcemapWidget figure. How can I update the ForcemapWidget figure?
I am desperately studying object-oriented programming, so I would appreciate it if you could teach me the basics as well. -
thank you for your reply.
I want to get coordinates on click of HeatmapWidget and change dimension of ForcemapWidget figure. How can I update the ForcemapWidget figure?
I am desperately studying object-oriented programming, so I would appreciate it if you could teach me the basics as well.@Kotaro your widget has
self.forcemapWidget
, that's the one you want to update. -
Since your issue is solved, please mark the thread as solved using the "Topic Tools" button or the three dotted menu beside the answer you deem correct so other forum members may know a solution has been found :-)
-
Since your issue is solved, please mark the thread as solved using the "Topic Tools" button or the three dotted menu beside the answer you deem correct so other forum members may know a solution has been found :-)
-
Use
self.forcemapWidget
inonclick
. -
def onclick(self,event): x,y=event.xdata,event.ydata forcemap=self.forcemapWidget (x)
このようにしても更新できません。
何回もすみません。@Kotaro you should add a method to the ForcemapWidget class that takes that x value and do the required update.
-
@Kotaro you should add a method to the ForcemapWidget class that takes that x value and do the required update.
-
Sorry for being blunt but yes you are. Updating a widget by recreating it every time you want to change a value is wrong.
initUI should be used once at construction time to put the various pieces in place. You should then have a separate function that take that x value and update the canvas content however you see fit. Such a method can also be called from the initUI method.
-
Sorry for being blunt but yes you are. Updating a widget by recreating it every time you want to change a value is wrong.
initUI should be used once at construction time to put the various pieces in place. You should then have a separate function that take that x value and update the canvas content however you see fit. Such a method can also be called from the initUI method.
-
Sorry for being blunt but yes you are. Updating a widget by recreating it every time you want to change a value is wrong.
initUI should be used once at construction time to put the various pieces in place. You should then have a separate function that take that x value and update the canvas content however you see fit. Such a method can also be called from the initUI method.
wrote on 14 Feb 2023, 17:26 last edited by@SGaist
I changed it like this but it doesn't work.class HeatmapWidget(QWidget): def __init__(self): super().__init__() self.forcemapWidget=ForcemapWidget() fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def onclick(self, event): x, y = event.xdata, event.ydata self.forcemapWidget.click(x) class ForcemapWidget (QWidget): def __init__(self): super ().__init__ () self.figure=plt.figure () self.ax=self.figure.add_subplot (111) heatmap=np.random.rand (256,256) self.im=self.ax.imshow (heatmap,cmap = "hot") canvas=FigureCanvas (self.figure) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def click(self,x): self.figure=plt.figure () self.ax=self.figure.add_subplot (111) heatmap=np.random.rand (int (x),256) self.im=self.ax.imshow (heatmap,cmap = "hot") canvas=FigureCanvas (self.figure) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) self.update()
-
You are rebuilding the whole widget and likely are getting warnings on the terminal.
Please take the time to learn how matplotlib works. What you have to do is update the plot and refresh the canvas.
-
You are rebuilding the whole widget and likely are getting warnings on the terminal.
Please take the time to learn how matplotlib works. What you have to do is update the plot and refresh the canvas.
-
@SGaist I can understand by looking at the example that I am doing the mouse events in one class.
I'm confused because there is no example of mouse events between two classes
Do you have a simple example?You handling the click event of your canvas, not multiple widgets. The fact that you called all methods click or onclick does not mean they are click event handler.
You really should use meaningful name for your methods and variables. That will make your code easier to follow and reason about.
-
You handling the click event of your canvas, not multiple widgets. The fact that you called all methods click or onclick does not mean they are click event handler.
You really should use meaningful name for your methods and variables. That will make your code easier to follow and reason about.
wrote on 14 Feb 2023, 21:20 last edited by Kotaro@SGaist
I made one that updates the color when clicked, but it doesn't.
Do you know why?import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) self.setWindowTitle ("MDI Application") sub2=QMdiSubWindow () form_widget=ForcemapWidget () sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show() sub3=QMdiSubWindow () form_widget=HeatmapWidget () sub3.setWidget (form_widget) sub3.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub3) sub3.show() class HeatmapWidget(QWidget): def __init__(self,parent=None): super().__init__() # self.forcemapWidget=ForcemapWidget() fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def onclick(self, event): self.force=ForcemapWidget() self.force.updates() class ForcemapWidget(QWidget): def __init__(self): super().__init__() self.figure = plt.figure(figsize=(5, 4)) ax = self.figure.add_subplot(111) heatmap = np.random.rand(256, 256) self.im = ax.imshow(heatmap, cmap="Oranges") self.colorbar = self.figure.colorbar(self.im) canvas = FigureCanvas(self.figure) layout = QVBoxLayout() layout.addWidget(canvas) self.setLayout(layout) def updates(self): self.im.set_cmap("Blues") self.figure.canvas.draw() app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
-
@SGaist
I made one that updates the color when clicked, but it doesn't.
Do you know why?import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) self.setWindowTitle ("MDI Application") sub2=QMdiSubWindow () form_widget=ForcemapWidget () sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show() sub3=QMdiSubWindow () form_widget=HeatmapWidget () sub3.setWidget (form_widget) sub3.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub3) sub3.show() class HeatmapWidget(QWidget): def __init__(self,parent=None): super().__init__() # self.forcemapWidget=ForcemapWidget() fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (canvas) self.setLayout (layout) def onclick(self, event): self.force=ForcemapWidget() self.force.updates() class ForcemapWidget(QWidget): def __init__(self): super().__init__() self.figure = plt.figure(figsize=(5, 4)) ax = self.figure.add_subplot(111) heatmap = np.random.rand(256, 256) self.im = ax.imshow(heatmap, cmap="Oranges") self.colorbar = self.figure.colorbar(self.im) canvas = FigureCanvas(self.figure) layout = QVBoxLayout() layout.addWidget(canvas) self.setLayout(layout) def updates(self): self.im.set_cmap("Blues") self.figure.canvas.draw() app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
wrote on 15 Feb 2023, 01:57 last edited byI understand this.
Here is the code as an example.import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QVBoxLayout,QApplication,QWidget,QMainWindow,QMdiArea,QAction,QMdiSubWindow,QTextEdit, \ QComboBox,QLineEdit,QPushButton,QCheckBox,QFormLayout import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class MDIWindow (QMainWindow): count=0 def __init__(self): super ().__init__ () self.mdi=QMdiArea () self.setCentralWidget (self.mdi) self.setWindowTitle ("MDI Application") sub2=QMdiSubWindow () form_widget=ForcemapWidget () sub2.setWidget (form_widget) sub2.setWindowTitle ("Sub Window 2") self.mdi.addSubWindow (sub2) sub2.show () sub3 = QMdiSubWindow() form_widget = HeatmapWidget(forcemap_widget=form_widget) sub3.setWidget(form_widget) sub3.setWindowTitle("Sub Window 3") self.mdi.addSubWindow(sub3) sub3.show() class HeatmapWidget(QWidget): def __init__(self, forcemap_widget, parent=None): super().__init__() self.forcemap_widget = forcemap_widget fig,ax=plt.subplots (figsize = (1,1)) heatmap=np.random.rand (256,256) im=ax.imshow (heatmap,cmap = "hot") fig.colorbar (im) ax.set_title ("Heatmap") fig.canvas.mpl_connect ("button_press_event",self.onclick) self.canvas=FigureCanvas (fig) layout=QVBoxLayout () layout.addWidget (self.canvas) self.setLayout (layout) def onclick(self, event): x, y = event.xdata, event.ydata self.forcemap_widget.updates() # 正 class ForcemapWidget(QWidget): def __init__(self): super().__init__() self.figure = plt.figure(figsize=(5, 4)) ax = self.figure.add_subplot(111) heatmap = np.random.rand(256, 256) self.im = ax.imshow(heatmap, cmap="Oranges") self.colorbar = self.figure.colorbar(self.im) self.canvas = FigureCanvas(self.figure) layout = QVBoxLayout() layout.addWidget(self.canvas) self.setLayout(layout) def updates(self): self.im.set_cmap("Blues") self.figure.canvas.draw() # self.show() app = QApplication(sys.argv) mdi = MDIWindow() mdi.show() app.exec_()
-
1/19