在pyside2中通过qml显示matplotlib中方便的科学计算绘图方式,找了好久,终于在万能的stackoverflow上找到,在此记录。原地址https://stackoverflow.com/questions/44474745/python-matplotlib-plot-inside-qml-layout
其原理通过matplotlib的 matplotlib.backends.backend_agg将图像绘制到FigureCanvasAgg并转成QImage。然后通过QQuickImageProvider将QImage传递给qml的Image。
test.py:
import sys import os import numpy as np from PySide2.QtGui import QGuiApplication from PySide2.QtQml import QQmlApplicationEngine import PySide2.QtQml as QtQml import PySide2.QtQuick as QtQuick import PySide2.QtGui as QtGui from matplotlib.figure import Figure from PySide2.QtCore import QObject from matplotlib.backends.backend_agg import FigureCanvasAgg class MImageProvider(QtQuick.QQuickImageProvider): figures = dict() def __init__(self): QtQuick.QQuickImageProvider.__init__(self, QtQml.QQmlImageProviderBase.Image) def addFigure(self, name, **kwargs): figure = Figure(**kwargs) self.figures[name] = figure return figure def getFigure(self, name): return self.figures.get(name, None) def requestImage(self, p_str, w, h): figure = self.getFigure(p_str) if figure is None: return QtQuick.QQuickImageProvider.requestImage(self, p_str, (w, h)) canvas = FigureCanvasAgg(figure) canvas.draw() w, h = canvas.get_width_height() img = QtGui.QImage(canvas.buffer_rgba(), w, h, QtGui.QImage.Format_RGBA8888).copy() return img class MyUpdateController(QObject): def __init__(self): print("hello world") self.imgprovider = MImageProvider() figure = self.imgprovider.addFigure("hello", figsize=(10, 10)) x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 22] y = np.sin(x) ax = figure.add_subplot(111) ax.plot(x, y) if __name__ == "__main__": app = QGuiApplication(sys.argv) print("hello qml") upp = MyUpdateController() #qmlRegisterType() engine = QQmlApplicationEngine() engine.addImageProvider('myimg', upp.imgprovider) engine.load(os.path.join(os.path.dirname(__file__), "main.qml")) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
main.qml:
import QtQuick 2.0
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: root
width: 1000
height: 700
visible: true
color: "#002d2d2d"
title: qsTr("Hello World")
Rectangle{
id: back
anchors.fill: parent
gradient: Gradient {
GradientStop {
position: 0
color: "#434343"
}
GradientStop {
position: 1
color: "#000000"
}
}
Image {
id: image
x: 26
y: 70
width: 510
height: 504
source: "image://myimg/hello"
fillMode: Image.PreserveAspectFit
}
}
}