2020.5.7 Pyside2 binding

Hey! Am I doing something wrong or the Pyside2 binding is not working on the 2020.5.7?

import fx
print(fx.ui)

AttributeError: module ‘fx’ has no attribute ‘ui’

print(fx.gui)

hum… I think you read too fast. On v7 for example the fx.ui returns
<silhouette.UIBinding object at 0x11234c368>

fx.gui returns True (which i understand its for testing the presence of the UI, but its not the UI binding itself on Pyside2 like on v7)

Oh sorry Magno, misunderstood what you were doing! Of course you know about fx.gui.
fx.ui is no more - but there is a way to get at the main window a different way.

Here is an example:

from PySide2 import QtWidgets
from PySide2 import QtCore
from PySide2.QtCore import *

import shiboken2

def down_cast_qobject(tp, obj):
    addresses = shiboken2.getCppPointer(obj)
    ptrs = list([p for p in addresses if p > 0])
    ptr = ptrs[0]
    wrapped = shiboken2.wrapInstance(ptr, tp)
    return wrapped

def get_main_window():
    widgets = QApplication.topLevelWidgets()
    for w in widgets:
        if w.objectName() == "mainWindow":
            return down_cast_qobject(QMainWindow, w)
    return None

app = QtWidgets.QApplication.instance()

# get the main Silhouette window
win = get_main_window()

# create a dock and add it
dock = QtWidgets.QDockWidget()
dock.setObjectName("hi_dock")
dock.setWindowTitle("HI!!")
win.addDockWidget(Qt.LeftDockWidgetArea, dock)

Thanks, that will do :slight_smile:

Is it a known pattern or bug that the following occurs with 2020.5.7:

from PySide2 import QtWidgets
app = QtWidgets.QApplication.instance()

type(app) == QtCore.QCoreApplication # !! This should be QtWidgets.QApplication

We’ve tried wrapping the app using the down_cast_qobject but after 2-3 uses of it, the .instance() starts returning None

def test():
    core = QtWidgets.QApplication.instance()
    return down_cast_qobject(QtWidgets.QApplication, core)

test() # Ok
test() # Maybe Ok
test() # Error, instance() is returning None now.

Just wondering if anyone else has experienced this. We’re going to try making sure the down_cast... is only ever called once in our tooling but it would be great to see the .instance() call return the correct object type.

Looks like a possible reference count issue. I use this code to get the main window:

from fx import *

from PySide2 import QtWidgets
from PySide2 import QtCore
from PySide2.QtCore import *
import shiboken2

def down_cast_qobject(tp, obj):
    addresses = shiboken2.getCppPointer(obj)
    ptrs = list([p for p in addresses if p > 0])
    ptr = ptrs[0]
    wrapped = shiboken2.wrapInstance(ptr, tp)
    return wrapped

def get_main_window():
    widgets = QApplication.topLevelWidgets()
    for w in widgets:
        if w.objectName() == "mainWindow":
            return down_cast_qobject(QMainWindow, w)
    return None

Right on - that works well enough! Unfortunately we have a good amount of tooling written to ask for the QApplication. Nothing is critical but means we have to have a decent amount of edge casing for Silhouette vs. other apps in our pipeline.

We settled on something like:

_app_ptr = None
def qApp():
    global _app_ptr
    if not _app_ptr:
        core = QtWidgets.QApplication.instance()
        _app_ptr = down_cast_qobject(QtWidgets.QApplication, core)
    return _app_ptr

As long as we’re using that things seem to operate as expected because we only cast once.

We’re also noticing that QtSvg is missing from the PySide2 libs - I assume because it’s only bundling what the main app uses. If QtSvg could be included it would be amazing! Thanks for your time!

Glad that’s working for you!

I think for 2021 I’ve added the rest of PySide2. I’ll double check.

1 Like