【发布时间】:2012-11-12 02:12:09
【问题描述】:
是否可以将 qt 枚举值转换为其键?
例如,我想从 QPrinter 类中获取“A4”,知道 QPrinter.A4 = 0
提前谢谢你
【问题讨论】:
是否可以将 qt 枚举值转换为其键?
例如,我想从 QPrinter 类中获取“A4”,知道 QPrinter.A4 = 0
提前谢谢你
【问题讨论】:
通常,您可以使用QMetaObject:
m = QtGui.QFrame.staticMetaObject
m.enumerator(m.indexOfEnumerator('Shadow')).valueToKey(QtGui.QFrame.Sunken)
'Sunken'
然而,QPrinter 似乎没有暴露元对象,所以你必须通过在 Python 中遍历QPrinter 的属性来做到这一点(幸运的是,PyQt 枚举是int 的子类,所以可以由isinstance识别):
page_sizes = dict((n, x) for x, n in vars(QtGui.QPrinter).items() if
isinstance(n, QtGui.QPrinter.PageSize))
page_sizes[QtGui.QPrinter.A4]
'A4'
【讨论】:
使用vars 和isinstance 构建枚举的双向映射:
>>> from PyQt4.QtGui import QPrinter
>>> pagesizes = {}
>>> for key, value in vars(QPrinter).iteritems():
... if isinstance(value, QPrinter.PageSize):
... pagesizes[key] = value
... pagesizes[value] = key
...
>>> pagesizes['A4']
0
>>> pagesizes[QPrinter.A4]
'A4'
>>> pagesizes[0]
'A4'
更新:
vars() 似乎不适用于所有版本的 PyQt,但 dir() 可能可以。因此,更强大的解决方案可能是:
>>> pagesizes = {}
>>> for key in dir(QPrinter):
... value = getattr(QPrinter, key)
... if isinstance(value, QPrinter.PageSize):
... pagesizes[key] = value
... pagesizes[value] = key
...
(注意:仅使用 pyqt-4.10.3/qt-4.8.5、pyqt-4.10/qt-5.1.1 和 pyqt- 进行测试5.1/qt-5.1.1)
【讨论】:
__dict__ 中,我认为没有其他方法可以生成枚举键(Qt 的元对象系统在这里也没有帮助,因为 QPrinter 不是 QObject)。
我根据 ecatmur 的回答实现了一个功能:
def qenum_key(base, value):
"""Convert a Qt Enum value to its key as a string.
Args:
base: The object the enum is in, e.g. QFrame.
value: The value to get.
Return:
The key associated with the value as a string, or None.
"""
klass = value.__class__
try:
idx = klass.staticMetaObject.indexOfEnumerator(klass.__name__)
except AttributeError:
idx = -1
if idx != -1:
return klass.staticMetaObject.enumerator(idx).valueToKey(value)
else:
for name, obj in vars(base).items():
if isinstance(obj, klass) and obj == value:
return name
return None
这首先尝试通过 QMetaObject 获取值,如果失败或不存在元对象,则使用纯 Python 方法。
【讨论】:
这个实现类似于The Compiler's one,但找出基类(QPrinter, QFrame 等)本身。
import sys
def enum_key(enum_val, with_val=False):
"""
Return name of Qt enum value.
`enum_val` - enum value
`with_val` (bool) - return value as part of name
"""
enum_cls = enum_val.__class__
parent = sys.modules.get(enum_cls.__module__)
for i in enum_cls.__qualname__.split(".")[:-1]:
parent = getattr(parent, i)
m = getattr(parent, "staticMetaObject", None)
if m:
idx = m.indexOfEnumerator(enum_cls.__name__)
name = m.enumerator(idx).valueToKey(enum_val)
else:
for n, val in vars(parent).items():
if isinstance(val, enum_cls) and val == enum_val:
name = n
break
return "%s (%d)" % (name, enum_val) if with_val else name
# from PyQt5 import QtPrintSupport
# print(enum_key(QtPrintSupport.QPrinter.A5, with_val=1))
# >> A5 (9)
【讨论】: