You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PyQt主窗口中嵌入matplotlib.pyplot.colorbar

问题:将Matplotlib Colorbar嵌入PyQt5 QMainWindow中

我是Python新手,当前项目已有以下功能:

  • 图片显示窗口
  • 读取图像颜色并在控制台输出
  • 根据颜色列表创建colorbar

现在需要把colorbar输出到QMainWindow中,而非独立弹出窗口。

当前效果:
当前效果

期望效果:
期望效果

项目代码

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() 

UI代码

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", "Линейка"))

解决方案

核心思路是利用Matplotlib的Qt后端组件,将Colorbar对应的Figure直接嵌入到UI预设的widget容器中,替代独立弹出窗口的方式。

1. 导入必要的Matplotlib Qt后端模块

在项目代码开头添加:

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

2. 修改colourBar方法

替换原有的独立窗口逻辑,将Colorbar渲染到QMainWindow的widget中:

def colourBar(self, colLst):
    # 清空容器内原有控件,避免重复添加
    for child in self.widget.children():
        child.deleteLater()

    i = 0
    bins = []
    for clr in colLst:
        bins.append(i)
        i += 0.5

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

    # 创建Matplotlib Figure和Axes
    fig = mpl.figure.Figure(figsize=(6, 1))
    ax = fig.add_subplot(111)
    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')

    # 将Figure转换为PyQt可识别的组件并添加到容器
    canvas = FigureCanvas(fig)
    layout = QtWidgets.QVBoxLayout(self.widget)
    layout.addWidget(canvas)

3. 优化导入与代码规范

  • 移除from matplotlib.pyplot import *(避免全局状态干扰),保留import matplotlib as mpl即可
  • 将collorsList += [xxx]替换为collorsList.append(xxx),符合Python列表操作规范

修改后的完整项目代码

import sys
import coordCatch
import matplotlib as mpl
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

from PIL import Image
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets 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.append(self.rgb_to_hex(cl[1]))
        collorsList.sort()
        print(collorsList)
#-------------------------

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

#----- Функция создания colorbar
    def colourBar(self, colLst):
        # 清空容器
        for child in self.widget.children():
            child.deleteLater()

        i = 0
        bins = []
        for clr in colLst:
            bins.append(i)
            i += 0.5

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

        # 创建Figure和Axes
        fig = mpl.figure.Figure(figsize=(6, 1))
        ax = fig.add_subplot(111)
        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')

        # 将Figure嵌入PyQt Widget
        canvas = FigureCanvas(fig)
        layout = QtWidgets.QVBoxLayout(self.widget)
        layout.addWidget(canvas)
#-------------

    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__': 
    main() 

内容的提问来源于stack exchange,提问作者Mikhail Borisov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:09:23