天道酬勤,学无止境

store state/expanded nodes of a jtree for restoring state

I am working with JTree.

I would like to know what is best the way to know which nodes are expanded in a JTree so as to save its state (i.e. save all expanded paths). So that if I call model.reload() the Jtree would not stay collapsed, but I will be able to restore its original state to the user, i.e., all expanded nodes will be expanded.

评论

Santhosh Kumar is one of my go-to guys for Swing Hacks.

Answer: http://www.javalobby.org/java/forums/t19857.html

You need to store the TreePaths that were expanded and expand them again after reloading the TreeModel. All TreePaths that have a descendant are considered to be expanded. P.S. if you deleted paths, check after reloading if the path is still available.

public void reloadTree(JTree jYourTree) {
    List<TreePath> expanded = new ArrayList<>();
    for (int i = 0; i < jYourTree.getRowCount() - 1; i++) {
        TreePath currPath = getPathForRow(i);
        TreePath nextPath = getPathForRow(i + 1);
        if (currPath.isDescendant(nextPath)) {
            expanded.add(currPath);
        }
    }
    ((DefaultTreeModel)jYourTree.getModel()).reload();
    for (TreePath path : expanded) {
        jYourTree.expandPath(path);
    }
}

I'm new to Java and this drove me nuts as well. But I figured it out...I think. Below works fine in my app, but I think it does have some risk of not working as expected in some unusual circumstances.

import javax.swing.JTree;
import javax.swing.tree.TreePath;

public class TreeState {

private final JTree tree;
private StringBuilder sb;

public TreeState(JTree tree){
    this.tree = tree;
}

public String getExpansionState(){

    sb = new StringBuilder();

    for(int i =0 ; i < tree.getRowCount(); i++){
        TreePath tp = tree.getPathForRow(i);
        if(tree.isExpanded(i)){
            sb.append(tp.toString());
            sb.append(",");
        }
    }

    return sb.toString();

}   

public void setExpansionState(String s){

    for(int i = 0 ; i<tree.getRowCount(); i++){
        TreePath tp = tree.getPathForRow(i);
        if(s.contains(tp.toString() )){
            tree.expandRow(i);
        }   
    }
}

}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Filtering on a JTree [closed]
    Closed. This question is opinion-based. It is not currently accepting answers. Want to improve this question? Update the question so it can be answered with facts and citations by editing this post. Closed 2 years ago. Improve this question Problem Applying filtering on a JTree to avoid certain nodes/leaves to show up in the rendered version of the JTree. Ideally I am looking for a solution which allows to have a dynamic filter, but I would already be glad if I can get a static filter to work. To make it a bit easier, let us suppose the JTree only supports rendering, and not editing. Moving
  • 将一些节点添加到基础模型后,如何刷新JTree?(How can I refresh a JTree after adding some nodes to the underlying model?)
    问题 首先,让我说我不使用DefaultTreeModel。 我实现了自己的TreeModel,所以无法使用DefaultXXX的东西。 问题是这样的:通过我的模型定义的一些addStuff()方法,我将节点添加到基础数据结构中。 然后,我通过在addStuff()函数内调用treeNodesChanged()来通知侦听器(我知道有treeNodesInserted方法,但这是同一回事。它只是用不同的方法通知侦听器)。 现在,侦听器之一是我主窗体中的静态类,并且此侦听器可以告诉JTree(也包含在我的主窗体中)刷新自身。 如何告诉JTree从模型中“重新加载”其部分或全部节点? 更新:发现这个问题,尽管不完全相同,但它给出了我想要的答案。 更新2:我的问题不是如何通知查看器(JTree),而是从模型发出通知后应以哪种方式重新加载jtree。 首先,我要说的是,我知道刷新树以反映基础更改的唯一方法是调用updateUI()或重用setModel()方法。 本质上,我的问题是这样的: 假设刚刚通过TreeModelListener API通知TreeModelListener模型发生了更改。 好吧,现在怎么办? 我有这个问题,因为JTree没有实现TreeModelListener。 因此,在我的情况下,侦听器是JTree的容器,或者是实现侦听器的内部类,与Jtree处于同一容器内。
  • 如何在JTree节点上添加复选框以管理多选?(How to add checkbox to JTree node to manage multiselection?)
    问题 我要构建的JTree具有包含复选框+图标+数据和树选择算法的节点。 回答1 这是完整的示例,演示了如何向Jtree节点添加复选框。 我将JTree与基于文件系统内容的节点一起使用。 我还使用AddCheckBoxToTree.CheckTreeManager类来管理选择或半选择选项。 采用 public AddCheckBoxToTree.CheckTreeManager getCheckTreeManager() { return checkTreeManager; } 选择树路径的方法。 例如: // clear all selected path in order TreePath[] paths=getCheckTreeManager().getSelectionModel().getSelectionPaths(); if(paths != null){ for(TreePath tp : paths){ getCheckTreeManager().getSelectionModel().removeSelectionPath(tp); } } 在这里,我粘贴了所有执行此操作的代码: package com.demo.tree.checkbox; import java.awt.BorderLayout; import java.awt.Color; import
  • 有关执行操作和使用具有多个视图的单个模型的不确定性(Uncertainties regarding Implementation of Actions and Usage of a single Model with multiple Views)
    问题 我是一个关于GUI编程的新手,也许我的问题有一个非常简单的解决方案。 我正在尝试实现一个Java Swing GUI,它可以用作数据结构树的编辑器。 GUI分为三个部分: 窗口左四分之一中的树查看器显示树结构数据。 右上方的大区域显示包含文本字段,表格等的编辑器。 树结构中的每种不同类型的对象都有其自己的编辑器,当在树查看器中选择该对象时,将显示该编辑器。 右下区域显示控制台查看器。 它用于显示有关特定操作的消息。 我正在努力服从我的程序中树查看器/编辑器中模型与可视化的严格分离。 因此,我创建了DefaultTreeModel(MyTreeModel)子类的实例,该实例存储对业务数据的引用,而JTree的子类的实例提供了树形结构的可视化表示。 我正在尝试实现使用Action类修改数据的功能。 任何操作(如CreateNode,RenameNode,DeleteNode)都在其自己的操作类(AbstractAction的子类)中实现。 这些动作在树查看器的上下文菜单和应用程序“编辑”菜单中使用。 但是我也想在GUI的编辑器部分重用其中的一些,例如RenameNode操作。 现在我被困在这里。 树查看器将显示一个图标以及树中每个节点的名称。 除其他内容外,相应的编辑器还包含一个JTextField,它显示关联节点的名称。
  • JTree Lazy Load Expand
    Hope you are doing fine. I have a JTree which I load lazily using database query (each node). I have a button on the screen and when user clicks the button I perform some insert/update/delete in database and then add the model back in Jtree with only root and its immediate children using an SQL (this collapses the tree and selection and all expanded nodes collapse which is expected since it is a lazily loaded tree) What I want to accomplish is before user clicks button to insert/update/delete, I read all the expanded state and save it in memory then when I re-initialize the JTree I loop
  • 来自 jtree 中 jcheckbox 的多个 ITEM_STATE_CHANGED 事件(Multiple ITEM_STATE_CHANGED events from jcheckbox in jtree)
    问题 有人,请解释我,它是如何工作的。 这是代码: package checkboxtree; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.util.EventObject; import java.util.Vector; import javax.swing.AbstractCellEditor; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing
  • Java:如何以编程方式选择和扩展JTree中的多个节点?(Java: How to programmatically select and expand multiple nodes in a JTree?)
    问题 我有一个JTree和awt.Canvas 。 当我从Canvas内的objList选择多个对象时,我希望所有选中的项目都显示在JTree内部。 举例来说,这意味着如果我选择了2个对象,则它们的根目录路径都应该扩展,并且每个选择的对象都应选择其对应的TreeNode 。 我的JTree具有TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION 。 这是我使用的扩展功能的示例: public void selectTreeNodes() { HashMap <String, MyEntity> entities = ...; Iterator it = entities.keySet().iterator(); while (it.hasNext()) { String str = it.next().toString(); MyEntity ent = entities.get(str); if (ent.isSelected()) { DefaultMutableTreeNode searchNode = searchNode(ent.getName()); if (searchNode != null) { TreeNode[] nodes = ((DefaultTreeModel) tree.getModel())
  • Multiple ITEM_STATE_CHANGED events from jcheckbox in jtree
    Somebody, explain me, please, how it works. Here is the code: package checkboxtree; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.util.EventObject; import java.util.Vector; import javax.swing.AbstractCellEditor; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.tree
  • Java: How to programmatically select and expand multiple nodes in a JTree?
    I have a JTree and an awt.Canvas. When i select multiple objects from within the Canvas into the objList, I want all the selected items to be shown inside the JTree as selected. That means for example if I have 2 objects selected, both their paths to root should be expanded, and also each selected object should have its corresponding TreeNode selected. My JTree has TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION. Here is a sample of the expand funcion i use : public void selectTreeNodes() { HashMap <String, MyEntity> entities = ...; Iterator it = entities.keySet().iterator(); while (it.hasNext
  • 使用 JTree 延迟加载展开折叠展开问题(Expand Collapse Expand Issue with JTree Lazy loading)
    问题 我已经使用延迟加载实现了一个树。 第一级节点在创建树时创建,而子节点仅在用户展开任何特定节点时创建。 数据来自数据库,我们向数据库发出查询以填充子节点。 实现了 TreeExpansionListener 并使用了 treeExpanded 方法的重写实现。 在扩展时,我删除所选节点的所有子节点,进行数据库查询并将记录作为子节点添加到所选节点。 在向树添加任何节点之前,会向该节点添加一个虚拟子节点。 使用 DefaultMutableTreeNode。 到目前为止一切顺利,按照预期运行良好。 问题 1 - 作为您,每次扩展都会调用 DB,因此如果节点折叠并再次扩展,我将进行一次 DB 旅行并再次处理......这个想法是如果已经扩展,则不要加载新的节点... 问题 2 - 如果我必须强制刷新,即重新加载树并保持扩展状态。 现在处于工作状态...如何在解决上述问题 1 的同时实现相同的目标? 感谢您对此的任何帮助。 回答1 正如 MadProgrammer 所解释的,这里有一个小演示示例,显示了当树在节点上扩展时动态加载数据的 JTree(并且有一个漂亮的加载栏作为奖励): import java.awt.BorderLayout; import java.awt.Dimension; import java.beans.PropertyChangeEvent; import
  • Java Swing:需要具有复选框的高质量开发的JTree(Java Swing: Need a good quality developed JTree with checkboxes)
    问题 我正在寻找一个JTree实现,该实现包含复选框,并且其中: 选择一个节点时,将自动选择其在树中的所有后继节点取消选择一个节点时,树中所有节点的后继者将自动被取消选择如果已经选择了父节点,并且从其后继节点之一中删除了所选节点,则将更改节点的颜色,以使您直观地知道,尽管选择了此父节点,但并未选择其所有后继节点(就像您选择时通用安装程序中要安装的组件) 单击节点将导致(无需按住“ Ctrl”键!): 如果该节点已被选中,则其所有后继节点都将变为未选中状态如果未选择该节点,则该节点及其所有后继节点都将被选中 我在网上搜索了一些简单的东西,但是找不到我想要的简单的东西。 有谁知道这种树的良好实现? 回答1 回答自己: 我决定与所有人共享我的代码。 这是结果的屏幕截图: 实现细节: 创建了一个扩展JTree的新类用我创建的新类替换了“ TreeCellRenderer”,其中显示了一个复选框和一个标签。 复选框选择被更改,而不是标签背景和边框。 完全终止了选择机制。 将“选择模型”替换为“ DefaultTreeSelectionModel”,它被覆盖的内联,具有空的实现创建新的事件类型以检查复选框创建了特殊的数据结构,有助于快速指示每个节点的状态 享受!! 这是一个用法示例: public class Main extends JFrame { private static final
  • 根据深度级别更改JTree节点图标(Change JTree node icons according to the depth level)
    问题 我正在寻找更改JTree(Swing)的不同图标的方法 Java文档说明了如何在节点是否为叶子的情况下更改图标,但这实际上不是我要搜索的内容。 对我来说,节点是叶子还是无关紧要,如果节点位于三个节点的第一/第二/第三深度级别,我只想更改图标。 回答1 作为自定义TreeCellRenderer的替代方法,可以将UI默认值替换为collapsedIcon和expandedIcon : Icon expanded = new TreeIcon(true, Color.red); Icon collapsed = new TreeIcon(false, Color.blue); UIManager.put("Tree.collapsedIcon", collapsed); UIManager.put("Tree.expandedIcon", expanded); TreeIcon只是Icon接口的一个实现: class TreeIcon implements Icon { private static final int SIZE = 14; private boolean expanded; private Color color; public TreeIcon(boolean expanded, Color color) { this.expanded = expanded
  • Expand Collapse Expand Issue with JTree Lazy loading
    I have implemented a tree using Lazy Loading. The 1st level nodes are created at the time of tree creation, where as the child nodes are created only when a user expands any particular node. The data is coming from DB, and we fire a query to the database so as to populate the child nodes. Implemented TreeExpansionListener and using overridden implementation of treeExpanded method. On expansion, I remove all child nodes for the selected node, make a DB query and add the records as child to the selected node. Before adding any node to a tree, a dummy child is added to the node. Working with
  • JTree 避免重新加载后崩溃(JTree avoid collapse after reload)
    问题 我试图找到一个解决方法来解决重新加载JTree后崩溃的问题。 情况: 树 [-] Office A |---[-] Office A.1 | |---[-] Office A.1.1 | |---[-] Office A.1.2 [-] Office B |---[-] Office B.1 | |---[-] Office B.1.1 | | |---[-] Office B.1.1.1 现在我必须添加Office A.1.3 。 为此,我获得了Office A.1并使用add(DefaultMutableTreeNode aNode)方法添加了Office A.1.3 。 OfficeA1.add(OfficeA13); 在此之后,我在树的DefaultTreeModel上调用reload方法。 问题是,在这个调用之后,树全部崩溃了: [+] Office A [+] Office B 而且我必须手动展开节点Office A以确保添加了节点... [-] Office A |---[-] Office A.1 | |---[-] Office A.1.1 | |---[-] Office A.1.2 | |---[-] Office A.1.3 [+] Office B 我的代码... DefaultMutableTreeNode root = new
  • 渲染时更改JTree行高调整大小的行为(Change JTree row height resizing behavior when rendering)
    问题 我想仅在选择节点时使用包含三个文本字段的自定义TreeCellRenderer,而在未选择节点时使用默认渲染器。 问题是,尽管我为面板设置了适当的首选和最小尺寸,但JTree不会更新已编辑的行高。 相反,当我使用与编辑器相同的面板时,它将正确呈现。 有人可以解释为什么会这样吗? 是否有建议的方法来实现与编辑类似的渲染调整大小行为? JTree是否提供一种直接设置它的方法,还是有必要扩展JTree或(更糟糕的)L&F? 注意:在BasicTreeUI.startEditing(TreePath path, MouseEvent event)方法后,我注意到以下代码行。 他们似乎负责调整大小: if(editorSize.width != nodeBounds.width || editorSize.height != nodeBounds.height) { // Editor wants different width or height, invalidate // treeState and relayout. editorHasDifferentSize = true; treeState.invalidatePathBounds(path); updateSize(); // To make sure x/y are updated correctly, fetch
  • 使用 DOM 解析器从 XML 文档创建 JTree(Creating a JTree out of an XML document using DOM parser)
    问题 package xml; import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.*; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.io.*; public class ThirdParser extends JFrame{ DocumentBuilderFactory factory; DocumentBuilder builder; File f; Document d; JTree tree; JScrollPane scroll; //------------------------------------------------------------------------------ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ new ThirdParser(); } }); } //---------------------------------------------------
  • changing how Nimbus LaF handles JTree node highlighting
    I have been working to transition a Java application from WindowsLookAndFeel to Nimbus, largely successfully, despite Nimbus foibles. My users overall like the Nimbus LaF but didn't like some details, some of which I changed by consulting previous questions on this site. Example: I copied the LeafIcon, ClosedIcon and OpenIcon from Windows LaF (which they liked) and use them in the Nimbus version, for a nice combination of LaFs. Stuck on one last (?) problem. I have a JTree with a subclassed DefaultCellRenderer to create the appropriate node displays. This works fine under WindowsLookAndFeel
  • JTree与表单生成器(JTree with form builder)
    问题 我使用默认的NetBeans jTree创建了一个表单,并在其上放置了一个jTree 。 然后以某种方式在其中创建一堆元素,例如“颜色”,“运动”,“食物”。 但是它不在创建代码中。 它来自哪里,我该如何编辑... 即使我做jTree1.removeAll(); 一切仍然存在...而且不是我向jTree工作中添加新项目的代码。 private void test(java.awt.event.MouseEvent evt) { //trying to remove all, but it does not remove anything jTree1.removeAll(); //it does print it in debug meaning that this function is called System.out.println("qwe"); //create the root node DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root"); //create the child nodes DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1"); DefaultMutableTreeNode
  • JTree 将节点的背景设置为不透明(JTree set background of node to non-opaque)
    问题 请查看 SSCCE。 如何使未选择的树节点的背景透明。 目前未选中节点的背景是白色的。 但是,如果未选中,我的单元格渲染器应将其绘制为非不透明(选中时为绿色……它的作用是什么)。 最后,我希望未选择的节点只是没有背景的文本,因为 SSCCE 中的红色区域在我的应用程序中具有渐变填充。 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; public class SimpleTree extends JFrame { public static void main(final String[] args) { new SimpleTree(); } public SimpleTree() { super("Creating a Simple JTree")
  • 将图标设置为Jtree中的每个节点(Set icon to each node in Jtree)
    问题 我想为JTree中的每个节点设置一个不同的图标,实际上是从数据库中加载每个节点,并带有一个“ while”,我将每个图标设置为根,叶或父级。 像这样: 我所有的声明都是全球性的: private ResultSet myResultSet; protected DefaultTreeModel treeModel; private DefaultMutableTreeNode rootNode,childNode,parent1,parent2; 这是我设置节点的代码: myResultSet=rtnNodes(); /*Method that returns a RS with my nodes*/ while(myResultSet.next()){ switch(myResultSet.getInt(1)){ /*The first column is the type of node: root, parent, leaf...*/ case 0: treeModel = new DefaultTreeModel((rootNode=new DefaultMutableTreeNode(myResultSet.getString(2)))); break; /*root node*/ case 1: case 4: parent1 = parent2 =