Как встроить matplotlib.colorbar в пользовательский интерфейс PyQt5

Есть окно для вывода изображения, есть функция считывания и вывода в консоли цветов на нем, есть функция создания colorbar на основе полученного списка цветов.

Подскажите, пожалуйста, что нужно сделать, чтобы вывести colorbar на QMainWindow.

Так это выглядит сейчас:

Так это выглядит сейчас


Так хотелось бы, что бы выглядело:

Так хотелось бы, что бы выглядело:


main.py:

import sys
import coordCatch
import matplotlib as mpl

from PIL import Image
from PyQt5 import QtWidgets, QtCore

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from matplotlib.pyplot import *

class graphicsScene(QtWidgets.QGraphicsScene):
    clicked = pyqtSignal()

    def __init__(self, parent=None):

        super(graphicsScene, self).__init__(parent)


class ExampleApp(QtWidgets.QMainWindow, coordCatch.Ui_MainWindow):
    def __init__(self):
        super(ExampleApp, self).__init__()
        self.setupUi(self)
        self.resize(640, 640)  

        self.gscene = graphicsScene()        
        self.graphicsView.setScene(self.gscene)
        self.graphicsView.show()

        pic = 'image.png'
        self.image = QImage(pic)
        pixmap = QGraphicsPixmapItem(QPixmap.fromImage(self.image))
        self.graphicsView.scene().addItem(pixmap)

        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, 
                                               self)
#-----Блок обработки изображения и создание списка цветов
        collorsList = []
        imag = Image.open(pic)
        collors = imag.getcolors()
        for cl in collors:
            if cl[0] > 30000:
                collorsList += [self.rgb_to_hex(cl[1])]
        collorsList.sort()
        print(collorsList)
#-------------------------

        self.radioButton.toggled.connect(lambda: self.colourBar(collorsList))

#----- Функция создания colorbar
    def colourBar(self, colLst):
        
        i = 0
        bins = []
        for clr in colLst:
            bins += [i]
            i += 0.5

        cmap = mpl.colors.ListedColormap(colLst)
        norm = mpl.colors.BoundaryNorm(boundaries=bins, 
                                       ncolors=len(cmap.colors)-1 )

        fig, ax = subplots(figsize=(6, 1))
        fig.subplots_adjust(bottom=0.5)
        cb2 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
        norm=norm,
        boundaries= [-.1] + bins + [2.1],
        ticks=bins,
        spacing='uniform',
        orientation='horizontal')
        cb2.set_label('Custom colour bar')
        show()
#-------------

    def rgb_to_hex(self, rgb):
            return '#%02x%02x%02x' % rgb



def main():
    app = QtWidgets.QApplication(sys.argv) 

    window = ExampleApp()
    window.show() 
    app.exec_()  

if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    main() 

coordCatch.py:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow): 
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(642, 491)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10, 10, 441, 331))
        self.graphicsView.setObjectName("graphicsView")
        self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
        self.radioButton.setGeometry(QtCore.QRect(490, 30, 131, 41))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.radioButton.setFont(font)
        self.radioButton.setObjectName("radioButton")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(10, 390, 441, 80))
        self.widget.setObjectName("widget")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.radioButton.setText(_translate("MainWindow", "Линейка"))

Ответы (1 шт):

Автор решения: S. Nick

Как вариант.

Обратите внимание, что я изменил некоторые строки, для того чтобы ваш пример заработал с моим изображением.

import sys
from PIL import Image

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

import matplotlib as mpl
from matplotlib.pyplot import *

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar


# from coordCatch import Ui_MainWindow
class Ui_MainWindow(object):
    def setupUi(self, MainWindow): 
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(642, 491)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10, 10, 441, 331))
        self.graphicsView.setObjectName("graphicsView")
        self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
        self.radioButton.setGeometry(QtCore.QRect(490, 30, 131, 41))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.radioButton.setFont(font)
        self.radioButton.setObjectName("radioButton")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(10, 390, 441, 80))
        self.widget.setObjectName("widget")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.radioButton.setText(_translate("MainWindow", "Линейка"))


class GraphicsScene(QtWidgets.QGraphicsScene):
    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(GraphicsScene, self).__init__(parent)


class ExampleApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(ExampleApp, self).__init__()
        self.setupUi(self)
        self.resize(640, 640)  

        self.gscene = GraphicsScene() 
        self.graphicsView.setScene(self.gscene)
        self.graphicsView.show()

# -----------> vvvvvv <-----------------------------------------------------------------
        pic = 'Ok.png'                                                      # 'image.png'                                    
        self.image = QImage(pic)
        pixmap = QGraphicsPixmapItem(QPixmap.fromImage(self.image))
        self.graphicsView.scene().addItem(pixmap)

        self.selection = QtWidgets.QRubberBand(
            QtWidgets.QRubberBand.Rectangle, self)
            
        #----- Блок обработки изображения и создание списка цветов
        collorsList = []
        imag = Image.open(pic)
        
#-        collors = imag.getcolors()
        collors = imag.getcolors(333)                                       # +++
# -----------------------------> ^^^ <-------------------------------------------
        
        for cl in collors:
            if cl[0] > 300:                                               # 30000:
# -------------------> ^^^ <------------------------------------------------------
                collorsList += [self.rgb_to_hex(cl[1])]
        collorsList.sort()
        print(collorsList)
        #-------------------------

        self.radioButton.toggled.connect(lambda: self.colourBar(collorsList))
        
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 
        self.fig, self.ax = subplots(figsize=(6, 1))
        self.fig.subplots_adjust(bottom=0.5)
        self.plotWidget = FigureCanvas(self.fig)
       
        self.layout = QtWidgets.QGridLayout(self.centralwidget)
        self.layout.addWidget(self.graphicsView, 0, 0)
        self.layout.addWidget(self.radioButton, 0, 1, 2, 1, alignment=Qt.AlignTop)
        self.layout.addWidget(self.plotWidget, 1, 0)
        self.addToolBar(QtCore.Qt.BottomToolBarArea, NavigationToolbar(self.plotWidget, self))        

        self.layout.setRowStretch(0, 3)
        self.layout.setRowStretch(1, 1)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        

#----- Функция создания colorbar
    def colourBar(self, colLst):
        i = 0
        bins = []
        for clr in colLst:
            bins += [i]
            i += 0.5

        cmap = mpl.colors.ListedColormap(colLst)
        norm = mpl.colors.BoundaryNorm(
            boundaries=bins, 
            ncolors=len(cmap.colors)-1 
        )

#        fig, ax = subplots(figsize=(6, 1))
#        fig.subplots_adjust(bottom=0.5)
        
        self.cb2 = mpl.colorbar.ColorbarBase(
        
#            ax, 
            self.ax,                                                             # +++

            cmap=cmap,
            norm=norm,
            boundaries=[-.1] + bins + [2.1],
            ticks=bins,
            spacing='uniform',
            orientation='horizontal'
        )
            
        self.cb2.set_label('Custom colour bar')

        self.plotWidget.draw()                                                     # +++


    def rgb_to_hex(self, rgb):
#            return '#%02x%02x%02x' % rgb
        return '#%02x%02x%02x%02x' % rgb                                           # +++
# -------------------------> ^^^^ <-----------------------------------------------------


if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    window = ExampleApp()
    window.show() 
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка