Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding a matplotlib chart into Qt/C++ application

I am developing an math-oriented GUI application in Qt/C++ and would like to embed a Python scripting, including NumPy and Matplotlib. Using Python C API, I finally managed to run a script, retrieve the values from the Python variables, including NumPy arrays etc. But I failed at drawing Matplotlib charts into my Qt/C++ application.

It is better to say, I have managed to save the chart's RGBA buffer to a variable using Python script, then get the value of the variable as a PyObject of buffer type, get the buffer and transform it to QImage then to QPixmap and finally put it into QLabel and display it.

But I am still missing its interactive behaviour, resizing etc. though it seems that it can be done by forwarding Qt mouse events to figure.canvas.button_press_event but it is then getting overly complicated... So I concluded I do not understand the principles of Python embedding well enough. I am missing something obvious.

I found some samples of embedding matplotlib charts into PyQt or PySide (i.e. written in Python) applications where I have seen something like QMainWindow.setCentralWidget(canvas) or layout.addWidget(canvas). Here canvas is FigureCanvasQTAgg object ( http://matplotlib.org/api/backend_qt4agg_api.html ).

This suggests that canvas inherits from QWidget. But when I try mimic this in C++ code using Python's C API, I end with just a PyObject *canvas, not knowing how to trasform it to a QWidget. This is my snippet without the important step:

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

As I wrote, I must be missing something obvious. I googled everywhere but without success. Any help would be very appreciated.

like image 512
V.K. Avatar asked Sep 07 '13 23:09

V.K.


People also ask

Is Pyqtgraph faster than matplotlib?

matplotlib: For plotting, pyqtgraph is not nearly as complete/mature as matplotlib, but runs much faster. Matplotlib is more aimed toward making publication-quality graphics, whereas pyqtgraph is intended for use in data acquisition and analysis applications.

Does matplotlib require QT?

Every time the installation of matplotlib requires qt lib, which will increase the download file size and disk usage up to several gigabytes. However matplotlib is a multi-backend tools, it can work with tk, gtk, qt and others where qt is optional.

What is Pyplot CLF ()?

The clf() function in pyplot module of matplotlib library is used to clear the current figure.


1 Answers

For PySide, I suggest reading this comp.lib.qt.pyside thread and also the section on type converters in the PySide docs. I can't vouch for the absolute correctness of this code, but it appears to do what you want.

For PyQt, the same comp.lib.qt.pyside thread links to an example of unwrapping SIP objects which is again exactly what you need.

like image 181
bks Avatar answered Sep 22 '22 02:09

bks