在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
}
}
}
|