我在 Qt 中有两个视图。两者都使用从 QAbstractListModel 派生的模型。
我想仅在两个视图之一中显示一个复选框。如果不创建全新的视图类,这可能吗?我用C++。
我尝试创建一个从我的主视图类派生的新视图类,并且仅覆盖 flags() 函数。这个想法是,两个视图将使用相同的模型对象,但一个视图将调用基类中的 flags(),而另一个视图将调用派生类中的 flags()。但派生类最终在这两种情况下都被使用。
您无法控制视图访问的方式
flags()
(您也不应该尝试这样做)。
正如评论中所建议的,您可以使用 QIdentityProxyModel,但覆盖
flags()
还不够,而且 data()
也必须被覆盖。
当
flags()
返回源标志 without Qt::ItemIsUserCheckable
时,它只会阻止用户检查该项目,但只要设置了 CheckStateRole
值,复选框仍然可见,这是合理的:顾名思义,该标志仅告诉该项目是否“可由用户检查”,但模型可能仍需要显示复选框以用于显示目的。
为了完全隐藏复选框,每当
data()
为 QVariant()
时,role
应返回 Qt::CheckStateRole
。
实际上,单独实现
data()
就足够了,但覆盖flags()
会更安全、适当和一致。
我不会尝试编写糟糕的 C++ 代码,但下面的 Python 示例应该足够清楚了:
class Proxy(QIdentityProxyModel):
def data(self, index, role=Qt.DisplayRole):
if role == Qt.CheckStateRole:
# in C++ this would be "return QVariant()", it's also possible
# in PySide/PyQt but actually unnecessary as it is considered
# implicit in this context.
return
# for any other role, return what the source model's data would
return super().data(index, role)
def flags(self, index):
# get the default result from flags() and return it by removing
# the unwanted flag in the meantime
return super().flags(index) & ~Qt.ItemIsUserCheckable
initStyleOption()
并从选项的 HasCheckIndicator
中取消设置
feature
标志,其效果与上面 data()
的效果类似,但在本例中我们存在相反的问题:“隐藏”检查状态只能防止使用鼠标切换它(因为没有可见的检查指示器可供单击),但也可以使用键盘(使用 Space bar 或 Select 来切换可检查项目)某些键盘和输入设备具有),因此您还应该确保 editorEvent()
不处理可能触发检查状态切换的键盘事件:
基本实现返回 false(表示它尚未处理该事件)。
在这种情况下,视图最终使用空格/选择键来开始编辑索引(假设模型可写并且视图的编辑触发器允许)。
如上所述,这是如何在 Python 中实现这一点的基本示例:
class NoCheckDelegate(QStyledItemDelegate):
def initStyleOption(self, opt, index):
# set up the option based on the index
super().initStyleOption(opt, index)
# remove the check indicator flag to prevent both displaying it and
# possible mouse interaction normally used for toggling it
opt.features &= ~opt.HasCheckIndicator
def editorEvent(self, event, model, opt, index):
if (
event.type() == event.KeyPress and (
event.key() == Qt.Key_Space
or event.key() == Qt.Key_Select
)
):
# "ignore" the event and let the view handle it if possible
return False
# just do anything else as expected from the delegate
return super().editorEvent(event, model, opt, index)