Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embeding PySide/PyQt widget into Qt/C++ application

Tags:

qt

pyqt

pyside

I have a C++/Qt application which should have its GUI extensible with modules. Extending should be simple and versatile. I am just checking a concept - is it possible to have this main C++/Qt application that would execute a Python/PySide/PyQt script which would create a QWidget (or derived class) instance and embed this widget into the main C++/Qt application?

Is there any working snippet to demonstrate the feasibility of this task? I.e. how to create and embed the widget? How to pass signals between the application and the widget?

like image 735
V.K. Avatar asked Mar 21 '14 08:03

V.K.


2 Answers

This question is a bit old, but in case someone else is face the same issue, I will try to give a useful answer.

I think it's possible. In the following example, I create a QApplication and QMainWindow in c++, embed a python interpreter, and then, on the python side, I create a QPushButton which I add to the main window.

Try this out:

#include <QApplication>
#include <QMainWindow>

#include <iostream>
#include "Python.h"

class PythonQt
{

public:

  PythonQt()
  {
    char name[] = "test";
    Py_SetProgramName(name);
    Py_Initialize();

    std::string code =
        "from PySide import QtGui\n"
        ""
        "all_widgets = QtGui.QApplication.instance().allWidgets()\n"
        "window = None\n"
        "for widget in all_widgets:\n"
        "    if str(widget.objectName()) == \"main_window\":\n"
        "      window = widget\n"
        "      break\n"
        ""
        "def message_box():\n"
        "    QtGui.QMessageBox.information(None, 'Test', 'Hello!', \ 
                      QtGui.QMessageBox.Ok)\n"
        "    QtGui.QApplication.instance().quit()\n"
        ""
        "button = QtGui.QPushButton('Press Me')\n"
        "button.clicked.connect(message_box)\n"
        "window.setCentralWidget(button)\n"
        "window.move(600, 300)\n"
        "window.show()";

    PyRun_SimpleString(code.c_str());
  }

};

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  QMainWindow win;
  win.setObjectName("main_window");

  PythonQt python_code;

  a.exec();
}

The python script is written here in a string to have everything in a single file, but you could of course read it in from a .py file.

Object ownership could be an issue though, as shown in the link given by Trilarion.

like image 177
Francois Avatar answered Sep 21 '22 09:09

Francois


I don't think this is possible. PySide/PyQt are wrappers around C++/Qt. That means you create C++ objects and Python wrapper objects and somehow the wrapper objects kind of refer to the C++ objects. This works one way as far as I know.

But you want the other way. Basically a wrapper around Python objects (which themselves are wrappers around C++ objects) to use in C++. I don't think PySide/PyQt are ready for thise. However it is possible to embed Python in other languages.

Also see How to shoot yourself in the foot. about the pitfalls of communication between C++/Qt and Python.

like image 26
Trilarion Avatar answered Sep 21 '22 09:09

Trilarion