注意:我问这个问题所以我可以为它提供答案(也许可以得到更好的答案)。解决方案不直观。
Qt的MacOS版本可能为用户提供了扩展整个QTreeView子树的方法(有一个开放的bug),但非MacOS版本肯定不会。我正在尝试实现“按住项目装饰的移动点击扩展整个子树”的行为。
有两个问题。两者中较容易的是检测到装饰上的移位点击。我通过截取扩展/折叠信号来做到这一点;他们检查了mousePressEvent设置的一些“全局”状态:
# similar implementation for _on_expanded
@pyqtSlot(QModelIndex)
def _on_collapsed(self, index):
if self._in_shift_press:
self._in_shift_press = False
_recursive_set_expanded(self, index, False)
def mousePressEvent(self, evt):
# Make shift-click expand/collapse all
if int(evt.modifiers() & Qt.ShiftModifier) != 0:
self._in_shift_press = True
try:
QTreeView.mousePressEvent(self, evt)
finally:
self._in_shift_press = False
这有点难看,但效果还不错。
更难的问题是实现_recursive_set_expanded(view,root,state)。递归崩溃非常快。但是,在索引的所有后代上调用view.setExpanded(True)的明显实现非常非常慢 - 约100个索引的多秒。问题不是昂贵的数据模型,因为view.expandAll()非常快。
一些消息来源显示,expand()的工作量远远少于expand()。但是,Qt API不公开expandSubtree()方法。如何快速实现这一目标,而不是深入挖掘私有实施?
答案 0 :(得分:4)
按'*'(星号)键可展开节点的子节点,这正是您想要的。您是否尝试使用假'*'按键调用keyPressEvent?
答案 1 :(得分:1)
由于expandAll()很快,而且崩溃(QModelIndex)很快,我的解决方案是只使用这两种方法并避免调用expand(QModelIndex):
def _recursive_set_expanded(view, root, desired):
"""For |root| and all its descendents, set the 'expanded' state to |desired|.
It is undefined whether expanded and collapsed signals are emitted."""
state = {}
def _recursive_get_state(view, model, index, under_root):
if index == root:
under_root = True
num_children = model.rowCount(index)
if num_children:
if under_root:
state[index] = desired
else:
state[index] = view.isExpanded(index)
for i in xrange(model.rowCount(index)):
_recursive_get_state(view, model, model.index(i,0, index), under_root)
_recursive_get_state(view, view.model(), QModelIndex(), False)
view.expandAll()
for k,v in state.iteritems():
if not v:
view.setExpanded(k, False)
答案 2 :(得分:0)
void MainWindow::expandNode(const QModelIndex &parentIndex, bool expand) {
tree->setExpanded(parentIndex, expand);
for (qint32 rowNum = 0; rowNum < treeModel->rowCount(parentIndex); ++rowNum) {
QModelIndex childIndex = treeModel->index(rowNum, 0, parentIndex);
tree->setExpanded(childIndex, expand);
expandNode(childIndex);
}
}
答案 3 :(得分:0)
由于我在尝试扩展子树时遇到了性能问题,而这个问题是第一个google结果,我将分享我的见解,尽管我使用的是C ++和Qt5。
TonyK的调用keyPressEvent的解决方案有效。但是,这个解决方案对我来说很笨拙,所以我检查了Qt源代码,它确实硬连接到Qt :: Key_Asterisk密钥。 (在QTreeView :: keyPressEvent中,如果你想亲眼看看。)
QTreeView :: keyPressEvent只是以深度优先的方式调用expand(),没有什么特别的,没有私有的api调用。当然,当我刚从keyPressEvent复制代码以便我的功能时,它起作用了:
QModelIndex current = currentIndex();
QStack<QModelIndex> parents;
parents.push(current);
QAbstractItemModel * mod = model();
while (!parents.isEmpty()) {
QModelIndex parent = parents.pop();
for (int row = 0; row < mod->rowCount(parent); ++row) {
QModelIndex child = mod->index(row, 0, parent);
if (!child.isValid())
break;
parents.push(child);
expand(child);
}
}
expand(current);
但是我想创建一个setExpandedRecursive(QModelIndex index, bool expanded)
函数,所以我检查了它们与我的代码的区别,并且只是他们为子树的根节点调用expand()
而不是第一个。所以我在我的功能中也这样做了,猜猜是什么,现在崩溃是问题而不是扩展。所以这是我的最终解决方案,适用于扩展和折叠子树:
void TreeViewClass::setExpandedRecursive(QModelIndex index, bool expanded)
{
if (!index.isValid())
return;
const QAbstractItemModel * model = index.model();
if (!expanded)
setExpanded(index, expanded);
for (int row = 0, count = model->rowCount(index); row < count; ++row)
setExpandedRecursive(model->index(row, 0, index), expanded);
if (expanded)
setExpanded(index, expanded);
}