我正在创建一个继承自
QLabel
的自定义小部件,我希望在我的小部件上有一个属性来表示向用户呈现时数据必须如何格式化。
为此,我正在尝试使用
Q_ENUMS
,但我没有取得太大成功。我可以让属性在 Designer 中显示,但保存的 UI 文件将枚举显示为 PyDMLabel::STRING
,而不是我所期望的 DisplayFormat::STRING
。
这是我的小部件代码:
class PyDMLabel(QLabel, PyDMWidget):
class DisplayFormat:
DEFAULT = 0
STRING = 1
DECIMAL = 2
EXPONENTIAL = 3
HEX = 4
BINARY = 5
Q_ENUMS(DisplayFormat)
"""
A QLabel with support for Channels and more from PyDM
Parameters
----------
parent : QWidget
The parent widget for the Label
init_channel : str, optional
The channel to be used by the widget.
"""
def __init__(self, parent=None, init_channel=None):
QLabel.__init__(self, parent)
PyDMWidget.__init__(self, init_channel=init_channel)
self.setTextFormat(Qt.PlainText)
self.setTextInteractionFlags(Qt.NoTextInteraction)
self.setText("PyDMLabel")
self._display_format_type = PyDMLabel.DisplayFormat.DEFAULT
@pyqtProperty(DisplayFormat)
def displayFormat(self):
return self._display_format_type
@displayFormat.setter
def displayFormat(self, new_type):
if self._display_format_type != new_type:
self._display_format_type = new_type
处理
Q_ENUMS
和PyQt的正确方法是什么?
更新:
从 PyQt-5.11 开始,
Q_ENUMS/Q_FLAGS
已被弃用,因此应使用 Q_ENUM/Q_FLAG
代替。这不会影响下面给出的原始解决方案,它仍然适用于 Q_ENUM
或 Q_ENUMS
。然而,在 PyQt6 中,这些函数不再可用,并已被 pyqtEnum 取代。这意味着用户定义的枚举现在必须是 enum.Enum 的子类并进行相应的修饰。为了与内置 API 保持一致,它们可能也应该被完全限定范围(即不再允许使用 PyDMLabel.STRING
),但这并不是严格必要的:
from enum import Enum
from PyQt6.QtCore import pyqtEnum
@pyqtEnum
class DisplayFormat(Enum):
DEFAULT = 0
STRING = 1
DECIMAL = 2
EXPONENTIAL = 3
HEX = 4
BINARY = 5
class PyDMLabel(QLabel, PyDMWidget):
DisplayFormat = DisplayFormat
原始解决方案(PyQt5):
为了让 Qt(Designer)看到枚举,PyQt 必须将其添加到自定义类的 meta-object 中。所以 Qt 永远不会将其称为
DisplayFormat::STRING
。
在 Qt 中,在类作用域中声明的枚举将其常量公开为类的成员。例如,QComboBox类定义了一个InsertPolicy枚举,并且常量可以这样引用:
QComboBox::InsertAtTop
。因此,在这方面,Qt Designer 插件中 PyQt enums 的行为完全符合预期,因为 ui 文件显示 PyDMLabel::STRING
。
但是,在 Python 代码中获得完全等效的行为需要一些额外的工作。我能想到的最接近的是:
class DisplayFormat:
DEFAULT = 0
STRING = 1
DECIMAL = 2
EXPONENTIAL = 3
HEX = 4
BINARY = 5
class PyDMLabel(QLabel, PyDMWidget, DisplayFormat):
DisplayFormat = DisplayFormat
Q_ENUM(DisplayFormat)
这将仍然导致Qt Designer使用
PyDMLabel::STRING
(如预期)。但 Python 代码现在可以通过以下任意方式访问常量:
PyDMLabel.STRING
PyDMLabel.DisplayFormat.STRING
DisplayFormat.STRING
事实上,如果您不介意失去第二个选项,您可以进一步简化事情:
class DisplayFormat:
DEFAULT = 0
...
class PyDMLabel(QLabel, PyDMWidget, DisplayFormat):
Q_ENUM(DisplayFormat)
PS:
在 PyQt5 中,枚举类的 type 是什么并不重要 - 所以它可以是
int
的子类、普通 object
,甚至是 python enum
。