Need help with custom enum properties in Qt6 Designer
Ivan Sinkarenko
ivan.sinkarenko at cern.ch
Mon Mar 4 15:58:37 GMT 2024
Hi Phil,
Thanks for the info. Do you think this could be addressed in future
releases? My project has a frequent use of designer plugins that have
custom enum properties, so I would be interested to solve it.
Potentially I could give you some assistance?
I've tried to investigate the flow myself a bit, here's what I found:
1. When setting a new value, QMetaProperty::write() is called
2. It recognizes that it receives a new int value, and tries to convert
it to the target type
3. Target type is derived from a meta type, referenced by the meta
property, through a call "QMetaType t(mobj->d.metaTypes[data.index(mobj)]);"
4. This target type for some reason has ID = 0 (i.e. UnknownType, as
defined by QMetaType::Type)
5. Conversion fails early, rejecting UnknownType, chained through
QMetaProperty::write() -> QVariant::convert() -> QMetaType::canConvert()
6. QMetaProperty::write() returns early.
Thanks,
Ivan
On 01/03/2024 18:50, Phil Thompson wrote:
> On 01/03/2024 17:24, Ivan Sinkarenko wrote:
>> Hi everybody,
>>
>> I've seen there's been a lot happening with enums in PyQt6,
>> and I've managed to adapt to most of the problems, except one.
>> I cannot figure out how to make custom enums work in custom widgets
>> that are exposed to Qt Designer.
>>
>> This is my simplified code:
>>
>> ----------------------------------------------------------------------
>> import enum
>> from PyQt6 import QtDesigner, QtGui, QtWidgets, QtCore
>>
>> class MyWidget(QtWidgets.QWidget):
>>
>> @QtCore.pyqtEnum
>> class MyEnum(enum.IntEnum):
>> ONE = enum.auto()
>> TWO = enum.auto()
>>
>> def __init__(self, *args, **kwargs) -> None:
>> super().__init__(*args, **kwargs)
>> self._prop = MyWidget.MyEnum.TWO
>>
>> @QtCore.pyqtProperty(MyEnum)
>> def prop(self):
>> print(f'Getting property val {self._prop}')
>> return self._prop
>>
>> @prop.setter
>> def prop(self, new_val):
>> print(f'Setting new property val {new_val}')
>> self._prop = new_val
>>
>> class Plugin(QtDesigner.QPyDesignerCustomWidgetPlugin):
>>
>> def name(self):
>> return "MyWidget"
>>
>> def group(self):
>> return "Buttons"
>>
>> def isContainer(self):
>> return False
>>
>> def createWidget(self, parent):
>> return MyWidget(parent)
>>
>> def icon(self):
>> return QtGui.QIcon()
>>
>> def toolTip(self):
>> return ""
>>
>> def whatsThis(self):
>> return ""
>>
>> def includeFile(self):
>> return "pyqt6_enum_designer_poc_plugin"
>> ----------------------------------------------------------------------
>>
>> I want an enum property to be displayed in the PropertySheet.
>> It's correctly represented by a combobox showing ONE and TWO as
>> available options.
>>
>> TWO is correctly selected by default. However, when in Property sheet
>> I try to set it to ONE,
>> as soon as I click away from there, it's reset back to TWO. In fact,
>> the setter does not get called,
>> since the message inside is never printed. (Getter message is being
>> printed).
>>
>> Properties do work without issues, if they have built-in types, such
>> as QColor,
>> or even native enums, such as Qt.Orientation.
>>
>> To try this code, you can save this code to
>> "pyqt6_enum_designer_poc_plugin.py" and run like so:
>> PYQTDESIGNERPATH=$(pwd) designer
>>
>> I use Qt Designer 6.6.2 and:
>> - PyQt6 6.6.1
>> - PyQt6-Qt6 6.6.2
>> - PyQt6-sip 13.6.0
>>
>> (Also tried with PyQt6-6.5.3 PyQt6-Qt6-6.5.3, same result)
>>
>> There used to be a way to make this work in PyQt5, but in PyQt6 I
>> tried multiple approaches without luck.
>> If anybody knows the correct path, that would be very appreciated!
>>
>> Thanks,
>> Ivan
>
> This is ringing a faint bell. I looked at it a long time ago and found
> that Designer was just not making the normal call to write the changed
> property value, maybe due to some sort of "optimisation". There may be
> something wrong in the way that PyQt creates the QMetaObject for the
> Python class but I never managed to get to the bottom of it.
>
> Sorry for not being more helpful.
>
> Phil
More information about the PyQt
mailing list