我有一个
QTreeWidgetItem
,我想在某些情况下禁用它,以防止用户使用不兼容的选项。我正在使用 Qt 5.15.2。
QTreeWidgetItem 有一个功能,
QTreeWidgetItem::setDisabled(bool disabled)
,但遗憾的是这似乎只是将其变灰 - 它并不能阻止用户单击箭头并展开或取消展开树项目。
当然有
QTreeWidgetItem::setExpanded(bool expand)
,但是这只设置一次 - 它不会阻止用户扩展。
是否有某种方法可以完全禁用树项目,以便用户无法打开它?我尝试了
QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
将标志设置为 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
信号,可能会在使用这些信号的自定义实现中导致某种程度的递归。
您可以作为一种简单的方法来处理鼠标按下事件。有两种方法可以做到这一点:
#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
)来启用/禁用扩展项目。