7

約 100000 以上のノードを持つ JTree があります。次に、ツリー全体を展開します。そのために、ここで見つけたソリューションを使用します。

私の問題は、このような大きなツリーの展開に 60 秒以上かかることです。これはあまり便利ではありません。拡張をスピードアップする方法について誰か提案がありますか?

4

6 に答える 6

3

150,000 個のノード (19,000 個以上の開くことができるノード) を含むツリーでも同じ問題が発生しました。そして、メソッドをオーバーライドするだけで、すべて展開の期間を 5 で割りましたgetExpandedDescendants

JTree tree = new javax.swing.JTree()
{
    @Override
    public Enumeration<TreePath> getExpandedDescendants(TreePath parent)
    {
        if (!isExpanded(parent))
        {
            return null;
        }
        return java.util.Collections.enumeration(getOpenedChild(parent, new javolution.util.FastList<TreePath>()));
    }

    /**
     * Search oppened childs recursively
     */
    private List<TreePath> getOpenedChild(TreePath paramTreeNode, List<TreePath> list)
    {
        final Object parent = paramTreeNode.getLastPathComponent();
        final javax.swing.tree.TreeModel model = getModel();
        int nbChild = model.getChildCount(parent);
        for (int i = 0; i < nbChild; i++)
        {
            Object child = model.getChild(parent, i);
            final TreePath childPath = paramTreeNode.pathByAddingChild(child);
            if (!model.isLeaf(child) && isExpanded(childPath))
            {
                //Add child if oppened
                list.add(childPath);
                getOpenedChild(childPath, list);
            }
        }
        return list;
    }
};

すべてのアクションを展開するのにかかる時間は 25 秒から 5 秒に短縮されました。現在もパフォーマンスの改善に取り組んでいます。

于 2013-10-25T09:16:32.733 に答える
1

私は解決策を試しました、あなたも使用します。

私の意見の後、そこに提示されたコードは最適ではありません:-最も深い非リーフノードに対してのみ呼び出すのではなく、すべてのノードに対してtree.expandPathを呼び出します(リーフノードでexpandPathを呼び出しても効果はありません。JDKを参照してください)

これがより速いはずの修正されたバージョンです:

// If expand is true, expands all nodes in the tree.
    // Otherwise, collapses all nodes in the tree.
    public void expandAll(JTree tree, boolean expand) {
        TreeNode root = (TreeNode)tree.getModel().getRoot();
        if (root!=null) {   
            // Traverse tree from root
            expandAll(tree, new TreePath(root), expand);
        }
    }

    /**
     * @return Whether an expandPath was called for the last node in the parent path
     */
    private boolean expandAll(JTree tree, TreePath parent, boolean expand) {
        // Traverse children
        TreeNode node = (TreeNode)parent.getLastPathComponent();
        if (node.getChildCount() > 0) {
            boolean childExpandCalled = false;
            for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode)e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                childExpandCalled = expandAll(tree, path, expand) || childExpandCalled; // the OR order is important here, don't let childExpand first. func calls will be optimized out !
            }

            if (!childExpandCalled) { // only if one of the children hasn't called already expand
                // Expansion or collapse must be done bottom-up, BUT only for non-leaf nodes
                if (expand) {
                    tree.expandPath(parent);
                } else {
                    tree.collapsePath(parent);
                }
            }
            return true;
        } else {
            return false;
        }
    }
于 2010-10-15T21:20:00.607 に答える
1

幅優先 (すべての直接の子を調べる) または深さ優先 (1 つの子のすべての子孫を調べる) のいずれかの表示戦略を考える必要があると思います。100,000 は画面に表示するにはノードが多すぎるため、パンとズームについて考える必要があります。必要な子孫のサブセットを選択できるフィルターを考える必要があります。

1 つの戦略は、最上位の子を表示し、マウスが子に入ったときにそのすべての子孫を表示し、離れるときにそれらを折りたたむことです。このようにして、関心のある現在のサブツリーを表示するツリーをナビゲートできます。

于 2009-12-15T12:50:00.050 に答える
0

ええ、UI 要素を再考してください。JTree は、100,000 個のノードを表示するために探しているものではありません。テーブルが表示され、アイテムをクリックしてテーブル要素にドリルダウンできるものを使用します。次に、ユーザーが階層を上に移動できるように、パンくずリストのような履歴を作成します。

JTree を使用することに固執している場合は、再描画する方法を引き継ぐ方法がありますが、それが展開の問題に役立つかどうかはわかりません。

于 2009-12-15T13:20:30.160 に答える