如何在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
相关产品推荐
相关产品推荐

