当前位置: 首页 > 面试题库 >

展开折叠展开与JTree延迟加载有关的问题

孔飞翔
2023-03-14
问题内容

我已经使用延迟加载实现了一棵树。1级节点是在创建树时创建的,而子节点只有在用户扩展任何特定节点时才创建。

数据来自数据库,我们向数据库发出查询,以填充子节点。实现TreeExpansionListener并使用treeExpanded方法的重写实现。扩展时,我删除所选节点的所有子节点,进行数据库查询,并将记录作为子节点添加到所选节点。在将任何节点添加到树之前,将虚拟子节点添加到该节点。使用DefaultMutableTreeNode。

到目前为止,一切都很好,符合预期。

问题1-正如您一样,它是每个扩展的数据库调用,因此,如果某个节点折叠并再次扩展,我将进行一次数据库旅行,然后再次进行处理…想法是如果已经扩展,则不加载新的节点…

问题2-如果必须进行强制刷新,即重新加载树并保持扩展状态。现在处于工作状态…如何解决上述问题1?

感谢对此的任何帮助。


问题答案:

正如MadProgrammer解释的那样,这是一个小型演示示例,其中显示了一个JTree,它在树在节点上扩展时动态加载数据(并带有漂亮的加载栏作为奖励):

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

public class TestJTree {

    public static class MyTreeNode extends DefaultMutableTreeNode {

        private boolean loaded = false;

        private int depth;

        private final int index;

        public MyTreeNode(int index, int depth) {
            this.index = index;
            this.depth = depth;
            add(new DefaultMutableTreeNode("Loading...", false));
            setAllowsChildren(true);
            setUserObject("Child " + index + " at level " + depth);
        }

        private void setChildren(List<MyTreeNode> children) {
            removeAllChildren();
            setAllowsChildren(children.size() > 0);
            for (MutableTreeNode node : children) {
                add(node);
            }
            loaded = true;
        }

        @Override
        public boolean isLeaf() {
            return false;
        }

        public void loadChildren(final DefaultTreeModel model, final PropertyChangeListener progressListener) {
            if (loaded) {
                return;
            }
            SwingWorker<List<MyTreeNode>, Void> worker = new SwingWorker<List<MyTreeNode>, Void>() {
                @Override
                protected List<MyTreeNode> doInBackground() throws Exception {
                    // Here access database if needed
                    setProgress(0);
                    List<MyTreeNode> children = new ArrayList<TestJTree.MyTreeNode>();
                    if (depth < 5) {
                        for (int i = 0; i < 5; i++) {
                            // Simulate DB access time
                            Thread.sleep(300);
                            children.add(new MyTreeNode(i + 1, depth + 1));
                            setProgress((i + 1) * 20);
                        }
                    } else {
                        Thread.sleep(1000);
                    }
                    setProgress(0);
                    return children;
                }

                @Override
                protected void done() {
                    try {
                        setChildren(get());
                        model.nodeStructureChanged(MyTreeNode.this);
                    } catch (Exception e) {
                        e.printStackTrace();
                        // Notify user of error.
                    }
                    super.done();
                }
            };
            if (progressListener != null) {
                worker.getPropertyChangeSupport().addPropertyChangeListener("progress", progressListener);
            }
            worker.execute();
        }

    }

    protected void initUI() {
        JFrame frame = new JFrame(TestJTree.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyTreeNode root = new MyTreeNode(1, 0);
        final DefaultTreeModel model = new DefaultTreeModel(root);
        final JProgressBar bar = new JProgressBar();
        final PropertyChangeListener progressListener = new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                bar.setValue((Integer) evt.getNewValue());
            }
        };
        JTree tree = new JTree() {
            @Override
            @Transient
            public Dimension getPreferredSize() {
                Dimension preferredSize = super.getPreferredSize();
                preferredSize.width = Math.max(400, preferredSize.width);
                preferredSize.height = Math.max(400, preferredSize.height);
                return preferredSize;
            }
        };
        tree.setShowsRootHandles(true);
        tree.addTreeWillExpandListener(new TreeWillExpandListener() {

            @Override
            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
                TreePath path = event.getPath();
                if (path.getLastPathComponent() instanceof MyTreeNode) {
                    MyTreeNode node = (MyTreeNode) path.getLastPathComponent();
                    node.loadChildren(model, progressListener);
                }
            }

            @Override
            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {

            }
        });
        tree.setModel(model);
        root.loadChildren(model, progressListener);
        frame.add(new JScrollPane(tree));
        frame.add(bar, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestJTree().initUI();
            }
        });
    }
}


 类似资料:
  • 我有一个带有多个视图保持器的RecyclerView适配器。每个ViewHolder都有一个标题TextView和一个嵌套的RecyclerView,工作正常。但我想实现一个扩展/折叠函数,这样嵌套的RecyclerView就可以隐藏,直到单击标题为止。我使用此方法RecyclerView展开/折叠项目。它可以工作,但当我单击标题以展开嵌套的RecyleView时,recyclerview不会填充

  • 我创建了一个由某些菜单项组成的垂直列表菜单。单击任何菜单项时,列表将展开以显示其内部子菜单项。 还有,当页面加载时,其中一个菜单会根据页面自动展开。我使用了jquery toggle来实现这个功能,它工作得很好。 现在,我用这个菜单放置了折叠/展开箭头,类似于jquery accordian中的菜单,它们在click事件时切换。 我的问题是,当页面加载时,其中一个菜单项折叠,但箭头没有随之折叠,当

  • 展开或折叠代码 操作步骤: 菜单栏:Code —> Folding —> Expand 快捷键: Mac: command + “+” Windows\/Linux: Ctrl + "+" 展开或折叠代码 操作步骤: 菜单栏:Code —> Folding —> Collapse 快捷键: Mac: command + “-” Windows\/Linux: Ctrl + "-" 展开或折叠当前代

  • 问题内容: 我已经成功创建了一个函数来切换我的各个行以使用以下方式打开和关闭: 和 有关更多代码,请参见plunkr。请注意,“菜单”中的展开/折叠按钮。 但是,我现在想不出一种方法来打开和关闭所有行。我希望能够以某种方式在行上运行for循环,然后在需要时调用toggle,但是我这样做的尝试失败了。在下面看到它们: 关于如何正确切换所有行的任何想法? 问题答案: 将该指令与和指令结合使用,我们可以

  • 问题内容: 我能够展开和折叠单元格,但我想在UITableViewCell内调用函数(展开和折叠)以更改按钮标题。 问题答案: 如果你想在细胞获得更大的身体,那么,你有你的店,在使用: 然后,当您想在didSelectRow中展开一个时: 编辑 这将使单元动画自己变大,您不需要单元中额外的动画块。 编辑2

  • 本文向大家介绍jQuery实现表格展开与折叠的方法,包括了jQuery实现表格展开与折叠的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了jQuery实现表格展开与折叠的方法。分享给大家供大家参考。具体分析如下: 这是很人性化的一款特效代码,实现点击其中一个父级,另一个之前打开的父级会自动关闭 希望本文所述对大家的jQuery程序设计有所帮助。