从 PyQt5 迁移到 PySide2 时的 QVariant 替代方案
QVariant alternative when migrating from PyQt5 to PySide2
由于以下代码,我在从 PyQt5 切换到 PySide2 时遇到了一些问题:
class EnumModel(QtCore.QAbstractListModel):
def __init__(self, list_of_enums):
"""
Enumeration model
:param list_of_enums: list of enumeration values to show
"""
QtCore.QAbstractListModel.__init__(self)
self.items = list_of_enums
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() is True:
if role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(self.items[index.row()].value[0])
elif role == QtCore.Qt.ItemDataRole:
return QtCore.QVariant(self.items[index.row()].value[0])
return QtCore.QVariant()
代码在 PyQt5 下运行良好。
在我的迁移工作中,我发现 the official website 说:
PySide only supports PyQt's API 2 (see PSEP 101) for details.
Therefore Qt classes such as QStrings, QStringLists, and QVariants are
not available on PySide. Instead, you should simply use native Python
datatypes.
所以解决方案是(我猜)简单地将 QVariant
更改为 str
。当我这样做时,class 不会抛出任何错误,但它也不显示模型。
实际上函数 data
正在接收 role=13
而不是 role=QtCore.Qt.DisplayRole
。
我不知道这是 PySide2 的错误(在 Linux 下有点错误)还是因为其他原因。
一个最小可行的例子是这样的:
from PySide2.QtWidgets import *
from PySide2 import QtCore
from enum import Enum
class SomeEnum(Enum):
A = 'A'
B = 'B'
C = 'C'
class EnumModel(QtCore.QAbstractListModel):
def __init__(self, list_of_enums):
"""
Enumeration model
:param list_of_enums: list of enumeration values to show
"""
QtCore.QAbstractListModel.__init__(self)
self.items = list_of_enums
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() is True:
if role == QtCore.Qt.DisplayRole:
return self.items[index.row()].value[0]
elif role == QtCore.Qt.ItemDataRole:
return self.items[index.row()].value[0]
else:
print('not recognised')
return ""
if __name__ == '__main__':
import sys
model = EnumModel([SomeEnum.A, SomeEnum.A, SomeEnum.B, SomeEnum.C])
app = QApplication(sys.argv)
lst = QListView()
lst.setModel(model)
lst.show()
sys.exit(app.exec_())
问题是,当视图需要与角色 Qt::SizeHintRole
(13) 相关的信息时,您传递给它的是一个空字符串,而您必须 return None 或者干脆做没有 return 任何东西,因为它会干扰其他角色:
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
print(role)
if role == QtCore.Qt.DisplayRole:
return self.items[index.row()].value[0]
elif role == QtCore.Qt.ItemDataRole:
return self.items[index.row()].value[0]
else:
print('not recognised')
由于以下代码,我在从 PyQt5 切换到 PySide2 时遇到了一些问题:
class EnumModel(QtCore.QAbstractListModel):
def __init__(self, list_of_enums):
"""
Enumeration model
:param list_of_enums: list of enumeration values to show
"""
QtCore.QAbstractListModel.__init__(self)
self.items = list_of_enums
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() is True:
if role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(self.items[index.row()].value[0])
elif role == QtCore.Qt.ItemDataRole:
return QtCore.QVariant(self.items[index.row()].value[0])
return QtCore.QVariant()
代码在 PyQt5 下运行良好。
在我的迁移工作中,我发现 the official website 说:
PySide only supports PyQt's API 2 (see PSEP 101) for details. Therefore Qt classes such as QStrings, QStringLists, and QVariants are not available on PySide. Instead, you should simply use native Python datatypes.
所以解决方案是(我猜)简单地将 QVariant
更改为 str
。当我这样做时,class 不会抛出任何错误,但它也不显示模型。
实际上函数 data
正在接收 role=13
而不是 role=QtCore.Qt.DisplayRole
。
我不知道这是 PySide2 的错误(在 Linux 下有点错误)还是因为其他原因。
一个最小可行的例子是这样的:
from PySide2.QtWidgets import *
from PySide2 import QtCore
from enum import Enum
class SomeEnum(Enum):
A = 'A'
B = 'B'
C = 'C'
class EnumModel(QtCore.QAbstractListModel):
def __init__(self, list_of_enums):
"""
Enumeration model
:param list_of_enums: list of enumeration values to show
"""
QtCore.QAbstractListModel.__init__(self)
self.items = list_of_enums
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() is True:
if role == QtCore.Qt.DisplayRole:
return self.items[index.row()].value[0]
elif role == QtCore.Qt.ItemDataRole:
return self.items[index.row()].value[0]
else:
print('not recognised')
return ""
if __name__ == '__main__':
import sys
model = EnumModel([SomeEnum.A, SomeEnum.A, SomeEnum.B, SomeEnum.C])
app = QApplication(sys.argv)
lst = QListView()
lst.setModel(model)
lst.show()
sys.exit(app.exec_())
问题是,当视图需要与角色 Qt::SizeHintRole
(13) 相关的信息时,您传递给它的是一个空字符串,而您必须 return None 或者干脆做没有 return 任何东西,因为它会干扰其他角色:
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
print(role)
if role == QtCore.Qt.DisplayRole:
return self.items[index.row()].value[0]
elif role == QtCore.Qt.ItemDataRole:
return self.items[index.row()].value[0]
else:
print('not recognised')