Home > Back-end >  Updating an embeded matplotlib image in PyQt5
Updating an embeded matplotlib image in PyQt5

Time:12-05

I have a matplotlib image embedded in PyQt:

enter image description here

But am now having trouble updating it.

The UI and the initial embedding is set up as follows:

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    # Ui_MainWindow is a python class converted from .ui file
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.imageDisp = ImageDisplay() # Class definition below 

        layoutImage = self.Image_Area.layout() # Image_Area is a Qt Group Box
        if layoutImage is None:
            layoutImage = QVBoxLayout(self.Image_Area)
        ax_img = self.imageDisp.displayImage()
        canvas_image = FigureCanvas(ax_img.figure)
        layoutImage.addWidget(canvas_image)

        self.NextImageButton.clicked.connect(self.inc)

    def inc(self):
        self.imageDisp.nextImage()
        layoutImage = self.Image_Area.layout() 
        if layoutImage is None:
            layoutImage = QVBoxLayout(self.Image_Area)
        ax_img = self.imageDisp.UpdateImage()
        canvas_image = FigureCanvas(ax_img.figure)
        self.imageDisp.draw()
        layoutImage.addWidget(canvas_image)

And the ImageDisplay class is defined as follows:

class ImageDisplay(FigureCanvas): # FigureCanvas is matplotlib.backends.backend_qt5agg.FigureCanvasQTAgg
    def __init__(self):
        # Other attributes 
        fig = Figure()
        self.fig = fig
        self.axes = fig.add_subplot(111)

    def nextImage(self):
        # Do something here 
        self.UpdateImage()

    def UpdateImage(self):
        self.axes.imshow(np.asarray(IMAGE))
        return self.axes

    def displayImage(self):
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)
        self.axes.imshow(np.asarray(IMAGE)) 
        return self.axes

This does not update the image, but addWidget would create a new widget on top of it, resulting in a stacked plot:

enter image description here

I tried to find ways to remove the widget but to no avail so far. Is there a way I can properly remove this widget and make a new one for the updated image? Or is there another way to display and update an image embedded in PyQt?

CodePudding user response:

try this instead

from PyQt5 import QtWidgets
from PyQt5.QtCore import *  
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
from matplotlib import image
import matplotlib.pyplot as plt

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.imageDisp = ImageDisplay(self, width=5, height=4, dpi=100)
        self.imageDisp.displayImage()
        self.NextImageButton=QtWidgets.QPushButton('next image',self)
        self.NextImageButton.clicked.connect(self.inc)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.imageDisp)
        layout.addWidget(self.NextImageButton)
        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.show()

    def inc(self):
        self.imageDisp.nextImage()

class ImageDisplay(FigureCanvas): # FigureCanvas is matplotlib.backends.backend_qt5agg.FigureCanvasQTAgg
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.start=0
        self.files=['ball.png','image.jpg']
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.fig.clear()
        self.axes = self.fig.add_subplot(111)
        self.axes.clear()
        self.axes.axis('off')
        plt.draw()
        super(ImageDisplay, self).__init__(self.fig)
    def nextImage(self):
        # Do something here
        self.IMAGE = image.imread(self.files[self.start%2])
        self.UpdateImage()

    def UpdateImage(self):
        self.start =1
        self.axes.clear()
        self.axes.axis('off')
        self.axes.imshow(np.asarray(self.IMAGE))
        self.draw()
    def displayImage(self):
        self.IMAGE = image.imread(self.files[self.start%2])
        self.start =1
        self.axes.clear()
        self.axes.axis('off')
        self.axes.imshow(np.asarray(self.IMAGE))
        self.draw()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    sys.exit(app.exec_())
  • Related