如何在 Qt 中使一个视图显示复选框,而另一个视图不显示?

问题描述 投票:0回答:1

我在 Qt 中有两个视图。两者都使用从 QAbstractListModel 派生的模型。

我想仅在两个视图之一中显示一个复选框。如果不创建全新的视图类,这可能吗?我用C++。

我尝试创建一个从我的主视图类派生的新视图类,并且仅覆盖 flags() 函数。这个想法是,两个视图将使用相同的模型对象,但一个视图将调用基类中的 flags(),而另一个视图将调用派生类中的 flags()。但派生类最终在这两种情况下都被使用。

c++ qt model-view-controller
1个回答
0
投票

您无法控制视图访问的方式

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 barSelect 来切换可检查项目)某些键盘和输入设备具有),因此您还应该确保
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)
© www.soinside.com 2019 - 2024. All rights reserved.