我有一个Java SE 7应用程序,需要更新JTree
个节点。从Oracle使用此thread给出的教程中,没有给出关于如何在代码上更新标签(树上节点的显示文本)的提示。目前,我使用DefaultTreeModel
作为我的JTree
和DefaultMutableTreeNode
的模型作为所述树的节点。
为了进一步详细说明我正在处理的应用程序,我正在开发一个聊天工具,其中显示的联系人的每个帐户的可用性状态(无论是在线,离线等)。
问题是,如何更新特定节点的显示文本,而不是(最多)将其从父节点中删除,并将其添加到指定的索引上。像DefaultMutableTreeNode.setText("<new label>")
?
更新日期:2013年1月20日
重新定义问题以便澄清。
答案 0 :(得分:9)
也许如果您使用'nodeChanged()'而不是'reload()',您将获得所需的效果。
DefaultTreeModel类上有许多方法可以更改和重绘树的各个部分。 DefaultTreeModel上还有其他方法只会导致重绘。
您提到'重新加载(节点)'并注释到它会在您调用树时导致树崩溃。 'reload'导致从该节点开始完全重绘整个子树。 (但如果该节点不可见,则不会改变任何内容。)这称为“结构更改”。
'insertNodeInto()'和'removeNodeFromParent()'通过添加或删除节点然后重新绘制来修改树结构。
我认为'nodeChanged()'是您需要的,因为它只是通知模型节点中发生了某些变化,导致它以不同的方式显示。也许可显示的文本现在不同于它。也许您更改了节点中的用户对象。那是在节点上调用'nodeChanged()'的时候。
您应该尝试使用'nodeChanged()'代替您自己的代码中的'reload()'调用,该代码在折叠时以及在提供的示例程序vels4j中。这可能会解决问题。
请注意,在其他情况下,DefaultTreeModel上还有另外两个方法系列:
这些方法与树节点一起使用,并使用树路径来定义更改发生的位置。它们不会更改树下的数据结构,但会通知模型更改了某些内容,以便它可以通知侦听器实际重绘内容或以其他方式响应更改。
nodesWereInserted()
nodesWereRemovde()
nodesChanged()
nodeStructureChanged()
还有一组fire...()
方法在内部用于DefaultTreeModel以及您可能创建的任何子类。他们只是通知任何听众改变了一些事情。请注意,它们受到保护。
答案 1 :(得分:7)
这个简单且可执行的程序可以帮助您解决问题。
public class JTreeDemo extends JPanel
implements Runnable {
private JTree tree;
private DefaultTreeModel treeModel ;
private Random rnd = new Random();
private List<User> userList;
public JTreeDemo() {
super( );
//Create the nodes.
DefaultMutableTreeNode top =
new DefaultMutableTreeNode("Users");
treeModel = new DefaultTreeModel(top);
createNodes(top);
//Create a tree that allows one selection at a time.
tree = new JTree(treeModel);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
//Add the split pane to this panel.
add(treeView);
}
public String getRandomStatus() {
int nextInt = rnd.nextInt(100);
if( nextInt%2==0) {
return "Online";
} else {
return "Offline";
}
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
int nextInt = rnd.nextInt(10);
User user = userList.get(nextInt);
user.setStatus(getRandomStatus());
treeModel.nodeChanged(user);
} catch (InterruptedException ex) {
// handle it if necessary
}
}
}
private class User extends DefaultMutableTreeNode {
public String userName;
public String status;
public User(String name) {
userName = name;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatus() {
return status;
}
@Override
public String toString() {
String color = status.equals("Online") ? "Green" : "Red";
return "<html><b color='"+color+"'>"+
userName +"-"+status +"</b></html>";
}
}
private void createNodes(DefaultMutableTreeNode top) {
userList = new ArrayList() ;
for(int i=0;i<10;i++) {
User u1 = new User("User " + (i+1));
u1.setStatus("Online");
top.add(u1);
userList.add(u1);
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
JTreeDemo jTreeDemo = new JTreeDemo();
frame.add(jTreeDemo);
frame.pack();
frame.setVisible(true);
// update status randomly
Thread thread = new Thread(jTreeDemo);
thread.start();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
我已经添加了一个随机更新状态的线程,希望您可以根据需要进行修改。
输出:
修改强>
1.根据建议我删除了reload(node)
并添加了树模型重新加载。
答案 2 :(得分:0)
仅仅是为了记录(我投票给Lee Meador),DefaultTreeModel#nodeChanged(javax.swing.tree.TreeNode)是要走的路:
public class TestFrame extends JFrame {
public TestFrame() {
//create gui with simple jtree (and DefaultTreeModel)
JButton changeBtn = new JButton();
final JTree jTree = new JTree();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
changeBtn.setText("update selected node");
getContentPane().add(changeBtn, java.awt.BorderLayout.PAGE_END);
DefaultMutableTreeNode treeNode1 = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode treeNode2 = new DefaultMutableTreeNode("blue");
treeNode1.add(treeNode2);
treeNode2 = new DefaultMutableTreeNode("violet");
DefaultMutableTreeNode treeNode3 = new DefaultMutableTreeNode("red");
treeNode2.add(treeNode3);
treeNode3 = new DefaultMutableTreeNode("yellow");
treeNode2.add(treeNode3);
treeNode1.add(treeNode2);
jTree.setModel(new DefaultTreeModel(treeNode1));
getContentPane().add(jTree, BorderLayout.CENTER);
pack();
//add listener to button, to change selected node on button click
changeBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
DefaultMutableTreeNode dmt = (DefaultMutableTreeNode)jTree.getSelectionPath().getLastPathComponent();
//update content/representation of selected node
dmt.setUserObject("My update: " + new Date());
//nodeChanged
((DefaultTreeModel) jTree.getModel()).nodeChanged(dmt);
}
});
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TestFrame().setVisible(true);
}
});
}
}