1

I want to display greyscale images with pyqt5 GUI and update the image display continuously, but the matplotlib creates a new colorbar every time updating the display.

Below are the codes.

from PyQt5.QtWidgets import*

from matplotlib.backends.backend_qt5agg import FigureCanvas

from matplotlib.figure import Figure

class MplWidget(QWidget):
    
    def __init__(self, parent = None):

        QWidget.__init__(self, parent)
        
        self.canvas = FigureCanvas(Figure())
        
        vertical_layout = QVBoxLayout()
        vertical_layout.addWidget(self.canvas)
        
        self.canvas.axes = self.canvas.figure.add_subplot(111)
        self.setLayout(vertical_layout)

from PyQt5.QtWidgets import*
from PyQt5.uic import loadUi

from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)
import numpy as np
import random
     
class MatplotlibWidget(QMainWindow):
    
    def __init__(self):
        
        QMainWindow.__init__(self)

        loadUi("display_test.ui",self)

        self.pushButton_2.clicked.connect(self.update)
        self.addToolBar(NavigationToolbar(self.MplWidget.canvas, self))

        data = np.random.rand(512, 512)
        self.MplWidget.canvas.axes.clear()
        self.d = self.MplWidget.canvas.axes.imshow(data, cmap="gray", norm=None)#, vmin=-1.2, vmax=1.2, interpolation='none')
        self.MplWidget.canvas.figure.colorbar(self.d)
        self.MplWidget.canvas.draw()
        
    def update(self):
        data = np.random.randint(0,1024,(512,512))
        self.MplWidget.canvas.axes.clear()
        self.d = self.MplWidget.canvas.axes.imshow(data, cmap="gray", norm=None)
        self.MplWidget.canvas.figure.colorbar(self.d)
        self.MplWidget.canvas.draw()
        
app = QApplication([])
window = MatplotlibWidget()
window.show()
app.exec_()

If no self.MplWidget.canvas.axes.clear() in the update function, then the image display scale doesn't change when updating and the high-value images will look saturated, all white.

If I don't add self.MplWidget.canvas.figure.colorbar(self.d) in the update function, then the colorbar just stay unchanged.

The image shows the problem. enter image description here

billinair
  • 93
  • 1
  • 11
  • `self.MplWidget.canvas.figure.colorbar(self.d)` returns the colorbar instance. So you could remove it before adding a new one if you keep a pointer to it. Or maybe there's a colorbar method that updates the existing instance when the data changes, such as `update_normal()`? – alec Aug 12 '20 at 05:35
  • 2
    You need to explicitly create an ax for the colorbar and use that every time. Something like `self.MplWidget.canvas.figure.colorbar(self.d, cax=my_cbar_ax)`. Default, if no `cax` is given, matplotlib "removes" space from the main ax and adds a new ax for the colorbar. – JohanC Aug 12 '20 at 13:58
  • @JohanC Adding an ax works. Thanks! – billinair Aug 26 '20 at 19:04

0 Answers0