如何防止用户展开 QTreeWidgetItem?

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

我有一个

QTreeWidgetItem
,我想在某些情况下禁用它,以防止用户使用不兼容的选项。我正在使用 Qt 5.15.2。

QTreeWidgetItem 有一个功能,

QTreeWidgetItem::setDisabled(bool disabled)
,但遗憾的是这似乎只是将其变灰 - 它并不能阻止用户单击箭头并展开或取消展开树项目。

当然有

QTreeWidgetItem::setExpanded(bool expand)
,但是这只设置一次 - 它不会阻止用户扩展。

是否有某种方法可以完全禁用树项目,以便用户无法打开它?我尝试了

QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
将标志设置为 0,因此每个选项都应该被禁用,但这没有任何区别。

唯一剩下的方法是禁用每个孩子,但唯一的麻烦是这些孩子还有其他需要禁用和启用的情况,因此简单地重新启用它们是错误的 - 其中一些孩子仍然会需要关闭。我想你可以存储所有孩子之前的状态,但这很麻烦而且容易出错。

qt qt5 expand qtreewidget qtreewidgetitem
2个回答
0
投票

一种可能性是为父项以及当前项设置

Qt::ItemNeverHasChildren
标志。

请注意,该标志仅用于优化目的,但在 QTreeWidget 中使用它应该没问题。

只需确保项目展开,设置标志以及现有标志,并确保更新视口。

我无法真正用 C++ 编写,所以我不会冒险发布糟糕的代码,但这就是我在 PyQt/PySide 中的做法,这应该是非常不言自明的:

def setItemExpandable(item, expand):
    if expand:
        item.setFlags(item.flags() & ~Qt.ItemNeverHasChildren)
    else:
        if item.isExpanded():
            item.setExpanded(False)
        item.setFlags(item.flags() | Qt.ItemNeverHasChildren)

    if item.treeWidget():
        item.treeWidget().viewport().update()

您甚至可以在自定义 QTreeWidgetItem 子类中实现它,并始终将其用作树小部件的原型。

请注意,如果该项目已经是视图的一部分,

setExpanded(False)
显然会触发
collapsed
itemCollapsed
信号,可能会在使用这些信号的自定义实现中导致某种程度的递归。


0
投票

您可以作为一种简单的方法来处理鼠标按下事件。有两种方法可以做到这一点:

使用事件过滤器

#include <QApplication>
#include <QTreeWidget>
#include <QTreeWidgetItem>

class TreeWidgetItemDisabler : public QObject
{
protected:
    bool eventFilter(QObject *watched, QEvent *event) override
    {
        if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
        {
            QTreeWidgetItem *item = static_cast<QTreeWidget*>(watched->parent())->itemAt(static_cast<QMouseEvent*>(event)->pos());

            //this is just an example condition
            //you can customize this based on what items you don't want expanded
            //usint their position, data, object name, etc.
            if (item && item->isDisabled())
            {
                //return true to filter out the event
                return true;
            }
        }

        return QObject::eventFilter(watched, event);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTreeWidget treeWidget;
    TreeWidgetItemDisabler treeWidgetDisabler;
    //IMPORTANT: the viewport receives mouse events, not the tree widget
    treeWidget.viewport()->installEventFilter(&treeWidgetDisabler);

    QTreeWidgetItem parentItem(&treeWidget, QStringList("Parent Item"));
    QTreeWidgetItem childItem(&parentItem, QStringList("Child Item"));

    QTreeWidgetItem parentItem1(&treeWidget, QStringList("Parent Item1"));
    QTreeWidgetItem childItem1(&parentItem1, QStringList("Child Item1"));

    QTreeWidgetItem parentItem2(&treeWidget, QStringList("Parent Item2"));
    QTreeWidgetItem childItem2(&parentItem2, QStringList("Child Item 2"));

    //as an example, I disabled the item I don't want expanded
    //you may tweak that based on your conditions
    parentItem.setDisabled(true);

    treeWidget.show();

    return a.exec();
}

使用
mousePressEvent

#include <QApplication>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QMouseEvent>

class TreeWidget : public QTreeWidget
{
public:
    TreeWidget(QWidget *parent = nullptr) : QTreeWidget(parent) {}

protected:
    void mousePressEvent(QMouseEvent *event) override
    {
        QTreeWidgetItem *item = itemAt(event->pos());

        if (item && item->isDisabled())
        {
            //accept the event to to indicate that you want to handle the event yourself
            //then do nothing and just return
            event->accept();
            return;
        }

        QTreeWidget::mousePressEvent(event);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TreeWidget treeWidget;

    QTreeWidgetItem parentItem(&treeWidget, QStringList("Parent Item"));
    QTreeWidgetItem childItem(&parentItem, QStringList("Child Item"));

    QTreeWidgetItem parentItem1(&treeWidget, QStringList("Parent Item1"));
    QTreeWidgetItem childItem1(&parentItem1, QStringList("Child Item1"));

    QTreeWidgetItem parentItem2(&treeWidget, QStringList("Parent Item2"));
    QTreeWidgetItem childItem2(&parentItem2, QStringList("Child Item 2"));

    //as an example, I disabled the item I don't want expanded
    //you may tweak that based on your conditions
    parentItem.setDisabled(true);

    treeWidget.show();

    return a.exec();
}

您还可以使用标志(例如

isExpandable
)来启用/禁用扩展项目。

© www.soinside.com 2019 - 2024. All rights reserved.