Внедрение диаграммы matplotlib в приложение Qt/С++

Я разрабатываю математическое приложение GUI в Qt/С++ и хотел бы встроить скрипты Python, включая NumPy и Matplotlib. Используя API Python C, мне наконец удалось запустить script, получить значения из переменных Python, включая массивы NumPy и т.д. Но мне не удалось рисовать графики Matplotlib в моем приложении Qt/С++.

Лучше сказать, мне удалось сохранить буфер RGBA диаграммы в переменной с помощью Python script, затем получить значение переменной как PyObject типа буфера, получить буфер и преобразовать его в QImage, затем в QPixmap и, наконец, поместить его в QLabel и отобразить его.

Но я все еще не вижу его интерактивного поведения, изменения размера и т.д., хотя кажется, что это можно сделать, перенаправляя события мыши Qt на figure.canvas.button_press_event, но потом становится слишком сложным... Поэтому я пришел к выводу, что я не достаточно хорошо понимайте принципы внедрения Python. Мне не хватает чего-то очевидного.

Я нашел несколько примеров встраивания графиков matplotlib в PyQt или PySide (т.е. написанные в Python) приложениях, где я видел нечто вроде QMainWindow.setCentralWidget(canvas) или layout.addWidget(canvas). Здесь canvas - объект FigureCanvasQTAgg (http://matplotlib.org/api/backend_qt4agg_api.html).

Это говорит о том, что холст наследуется от QWidget. Но когда я пытаюсь имитировать этот код на С++, используя API Python C, я заканчиваю только холстом PyObject *, не зная, как преобразовать его в QWidget. Это мой фрагмент без важного шага:

//draw a figure in Python script called from C++ app
PyRun_SimpleString("import matplotlib\n"
"matplotlib.use('Qt4agg')\n" //use Qt4 backend
"import pylab\n"
"pylab.plot(randn(10))\n" //plot something
"fig = pylab.gcf()\n" //take current figure
"canvas = fig.canvas" //canvas is of FigureCanvasQTAgg type

//get canvas as PyObject
PyObject* m = PyImport_AddModule("__main__");
PyObject* canvas = PyObject_GetAttrString(m, "canvas");
//from what I know, canvas is a PyObject wrapped around an object derived from QWidget

//...
//... here I do not know how to convert canvas (i.e. PyObject) into canvasWidget (i.e. QWidget)???
//... 

//show chart as a widget
MyWindow.setCentralWidget(canvasWidget)

Как я уже писал, я должен упустить что-то очевидное. Я гугл везде, но безуспешно. Любая помощь будет очень оценена.

Ответ 1

Для PySide я предлагаю читать этот поток comp.lib.qt.pyside, а также раздел преобразователи типов в документах PySide. Я не могу ручаться за абсолютную правильность этого кода, но он, похоже, делает то, что вы хотите.

Для PyQt тот же самый поток comp.lib.qt.pyside ссылается на пример разворачивать объекты SIP, что опять-таки именно то, что вам нужно.