wxTreeCtrl::SelectItem太慢了,该怎么办?

编程语言 2026-07-08

我有一个名为 newSelections 的wxArrayTreeItemIds,希望用它来选中treectrl中的对应项:

m_processingTreeSelect = true;

auto startTime = std::chrono::steady_clock::now();
_TRACE("STARTED");

m_sceneTreeViewCtrl->Freeze();

for (Uint32 i = 0u; i < newSelections.size(); ++i)
{
    const wxTreeItemId& item = newSelections[i];
    m_sceneTreeViewCtrl->SelectItem(item);
}

m_sceneTreeViewCtrl->Thaw();

const auto endTime = std::chrono::steady_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();

_TRACE("DURATION(MS): " << duration);

为了防止死锁,我使用一个布尔变量m_processingTreeSelect:

m_sceneTreeViewCtrl->Bind(wxEVT_TREE_SEL_CHANGED, [&](){
    if (m_processingTreeSelect)
        return;

    wxArrayTreeItemIds itemIds;
    if (!m_sceneTreeViewCtrl->GetSelections(itemIds))
        return;

    m_processingTreeSelect = true;

    // Build selection
    Selection selection;
    for (auto item : itemIds)
    {
        if (isRootItem(item))
            continue;

        switch (getSubRootType(item))
        {
        case TreeViewItemType::MeshGroup:
        case TreeViewItemType::Light:
        {
            selection.m_entities.push_back(tryGetTreeItemIdentifier(item));
        }
        break;

        default:
            _ASSERT(false);
        }

    }

    // Push selection change
    beginSelectionChange(selection, false);

    m_processingTreeSelect = false;
});

拥有一个包含10000个元素的数组时,下面这段代码执行需要大约三分钟。相反,如果用鼠标手动选中树中的所有项(Shift+左键单击),速度就很快!

我尝试了Freeze/Thaw的做法,它有点帮助,但还不够。

怎么办?

解决方案

你在执行时肯定应该冻结树,但一次性处理10000项在任何合理的场景下都太多。对于这类项数的树,通常会等到父节点展开后再对项进行任何操作(甚至包括把它们添加到树中),因此真正的修复办法是仅选择当前显示的项,等到 wxEVT_TREE_ITEM_EXPANDING 之后再选中父节点下的所有项。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章