Results 1 to 6 of 6

Thread: Show widget with PySide2 embedded in Qt5 application

  1. #1
    Join Date
    Jul 2012
    Posts
    228
    Thanks
    19
    Thanked 14 Times in 13 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Smile Show widget with PySide2 embedded in Qt5 application

    Hi,

    I have embedded a Python interpreter in my Qt5.12.0 App. The interpreter is python 3.6, running on Ubuntu 18.04. Everything works as expected.
    But now I want to show a widget from a python script inside my application, with PySide2.


    Qt Code:
    1. import sys
    2. from PySide2.QtWidgets import QApplication, QLabel
    3.  
    4. app = QApplication(sys.argv)
    5. label = QLabel("<font color=red size=40>Hello World!</font>")
    6. label.show()
    7. app.exec_()
    To copy to clipboard, switch view to plain text mode 

    This works fine as a standalone PySide2 Qt application. But obviously I cant create another QApplication in my embedded interpreter, because my regular C++ application already does that.
    However, just doing

    Qt Code:
    1. label = QLabel("<font color=red size=40>Hello World!</font>")
    2. label.show()
    To copy to clipboard, switch view to plain text mode 

    doesnt work, which doesnt really surprise me.



    Question: How can I make this work?


    (Final goal would be to create a docking widget from python, so I would have to make it a child of my QMainWindow, or expose a C++ baseclass to derive from. But that's the next step I guess...)

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,689
    Thanks
    257
    Thanked 750 Times in 740 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Show widget with PySide2 embedded in Qt5 application

    In C++ you can access the global QApplication instance using qApp (or equivalently, QCoreApplication::instance()). Would that help (or work) in PySide?

    Another option - can you expose a QWindow from python that you could use to create a QWidget in C++ (QWidget::createWindowContainer()) or vice-versa?

    Just sort of guessing here. I know you can expose C++ bindings to python, so it would seem logical that you could expose a widget from the Qt side that could be used in a python app as a container for a python-side created child.

    Edit: Check out this stackoverflow post.
    Last edited by d_stranz; 14th February 2020 at 02:05.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    tuli (14th February 2020)

  4. #3
    Join Date
    Jul 2012
    Posts
    228
    Thanks
    19
    Thanked 14 Times in 13 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Show widget with PySide2 embedded in Qt5 application

    Thanks!

    After modifying the stackoverflow code to work with PySide2, it works fine for displaying a QMessageBox. For any QWidget derived item, the application crashes upon trying to draw it (so immediately), deep inside painting code.

    Qt Code:
    1. from PySide2.QtWidgets import QApplication, QLabel, QMessageBox, QPushButton
    2.  
    3. all_widgets = QApplication.instance().allWidgets()
    4. window = None
    5. for widget in all_widgets:
    6. if str(widget.objectName()) == "main_window":
    7. window = widget
    8. break
    9.  
    10. //works
    11. QMessageBox.information(window, 'Test', 'Hello!', QMessageBox.Ok)
    12.  
    13. //crash during paint
    14. label = QLabel("<font color=red size=40>Hello World!</font>")
    15. label.setParent(window)
    16. label.show()
    To copy to clipboard, switch view to plain text mode 


    backtrace: https://pastebin.com/d3qTSgef


    Smells a bit like a use-after-free, maybe there is an issue with having to specify that I take ownership of the widget or something ...

    Thanks again

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,689
    Thanks
    257
    Thanked 750 Times in 740 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Show widget with PySide2 embedded in Qt5 application

    it works fine for displaying a QMessageBox. For any QWidget derived item, the application crashes
    So, the big difference between QMessageBox and QWidget is that the message box is modal and runs its own event loop. Everything is self-contained and it does not need to pass events across the python - C++ border. I think the only thing the "window" argument does in the QMessageBox method is to tell Qt to center the message box on that window. It isn't establishing a QWidget parent-child relationship because QMessageBox::information() is a static method so therefore there is no actual QWidget instance created (i.e. for static methods of a class, no instance of the class is required to execute it. In this case, QMessageBox is equivalent to enclosing the method in a namespace).

    Smells a bit like a use-after-free
    If your code above represents a stand-alone python executable, then I would say that is the case. You create your QLabel, parent it with a widget on the C++ side, show it, and then your python program exits leaving an invalid pointer on the C++ side. Normally, calling setParent() would connect the parent to the child's destroyed() signal so the ownership could be cleaned up, but it seems like there is some synchronization problem between the two sides.

    Is there some way to keep your python program running? You basically want the C++ side to treat it like a DLL - it gets loaded and stays loaded until it is no longer needed.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  6. #5
    Join Date
    Jul 2012
    Posts
    228
    Thanks
    19
    Thanked 14 Times in 13 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Show widget with PySide2 embedded in Qt5 application

    Unfortunately there is no way to keep it running.

    Meanwhile i have found a somewhat complicated way. Turns out the PySide2+shiboken2+shiboken2_generator supports this.
    In fact there is an example in pyside_setup/examples/scriptableapplication that does what I want!

    Unfortunately the setup is somewhat complicated and timeconsuming. Essentially you have to build the three packages from source yourself, specifying the Qt installation (needs sources installed) you want to use those packages for. Then the build process will generate python bindings for every last Qt class automatically. This step takes an hour on my computer. Once the packages are installed (they need to be in a virtualenv btw) you are supposed to use the magic cmake file from the example which does a ton of magic and then it works with the example....

    So this proves it is possible.

    But the price is high. There are prebuild packages on their server, but they explicitly recommend to build from sources, and indeed i couldnt get the precompiled stuff to work at all. All this makes it hard to ship it to endusers.


    If someone has any more smart ideas ... they are welcome!

  7. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,689
    Thanks
    257
    Thanked 750 Times in 740 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Show widget with PySide2 embedded in Qt5 application

    In reading the python documentation on embedding it would seem (from section 1.4) that you could expose your main window pointer to the python interpreter, thereby permitting a python script from creating a widget owned by the QMainWindow instance.

    This keeps the Qt app as the driver for the script and should allow you to create external scripts that are basically nothing more than functions that the interpreter loads. Your previous approach seems to want to make the external python script the driver instead - basically not even using the embedded interpreter.

    Is this not doable? You might be able to adapt the Qt Plugin architecture for this - your python interpreter loads the python script and returns a QObject pointer to the python class that implements the plugin interface. The interface functionality is exposed by your app to define the protocol for the conversation between the python script and the Qt app.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 2
    Last Post: 6th February 2019, 23:15
  2. How to show the output of SHOW ERRORS from qt application?
    By Ahmed Abdellatif in forum Qt Programming
    Replies: 1
    Last Post: 6th May 2018, 08:38
  3. Replies: 4
    Last Post: 18th October 2013, 17:15
  4. Replies: 6
    Last Post: 24th November 2011, 09:54
  5. Qt Creator Can't show the qwt widget in the embedded designer
    By SamT in forum Qt Tools
    Replies: 2
    Last Post: 30th May 2011, 21:07

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.