Let's say I have a python enum:
class UserState(Enum):
OFFLINE = auto()
ONLINE = auto()
BUSY = auto()
I can access the different options with UserState.ONLINE, UserState.OFFLINE or UserState.BUSY.
If I wanted to make this a QEnum so I can use it in QML, I'd need to wrap it inside a QObject like this:
class UserState(QObject):
@QEnum
class Options(Enum):
OFFLINE = auto()
ONLINE = auto()
BUSY = auto()
In QML I can access this enum now the same way I'd access a normal python enum in python. However if I wanted to access this enum from python, I'd have to write UserState.Options.ONLINE.
How can I create an enum that will work in python as well as QML using the same syntax?
I have found a solution for this which I will post in the answers section. However it involves nested metaclasses which just doesn't look right. I think the optimal solution would be a class that derives from QObject as well as Enum to have all the functionality for every context.
If anyone can provide a version which works like that, I will make that the accepted answer. Otherwise you can tell me, why my solution actually is a good one.
You can just call QEnum inside the class and define the enum outside.
Example (PySide6):
file: main.py
import sys
from enum import Enum
from pathlib import Path
from PySide6.QtCore import Property, QEnum, QObject
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import (
QmlElement,
QQmlApplicationEngine,
qmlRegisterSingletonInstance,
)
QML_IMPORT_NAME = "com.example.app"
QML_IMPORT_MAJOR_VERSION = 1
class Status(Enum):
Connected, Disconnected, Stale = range(3)
@QmlElement
class Enums(QObject):
QEnum(Status)
class App(QObject):
def __init__(self):
super().__init__(None)
@Property(int, constant=True)
def enumValue(self):
return Status.Connected.value
if __name__ == "__main__":
loop = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
app = App()
qmlRegisterSingletonInstance(QObject, "com.example.app", 1, 0, "App", app)
qml_file = Path(__file__).parent / "main.qml"
engine.load(str(qml_file))
sys.exit(loop.exec())
file: main.qml
import QtQuick
import com.example.app 1.0
Window {
visible: true
width: 1000
height: 700
title: "POC"
Rectangle {
color: App.enumValue == Enums.Status.Connected ? "green" : "red"
anchors.fill: parent
}
}
Full code here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With