可以让两棵树使用同一个选择模型,只需两行代码TreeSelectionModel model = jTree1.getSelectionModel(); jTree2.setSelectionModel(model);还有很多其他的Swing组件可以用类似的方法同步,例如JSlider,JProgressBar,JList等
to gtlang78() 那如何利用同一个选择模型实现两棵树展开的同步呢?
感谢gtlang78()的提示,如下代码实现了利用model和treepath来完成同步的动作 注意构造函数的第一行,将两个tree的model设为相同,以后就很方便的实现了两棵树的同步。 我觉得这种方法才真正解决了sharetop(天生不笨)的问题,建议给gtlang78()加分import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.tree.*; import javax.swing.event.*;public class Tree extends JFrame { JTree tree1 = new JTree(); JTree tree2 = new JTree(); public Tree(){ tree2.setModel(tree1.getModel()); tree1.addTreeExpansionListener(new TreeExpansionAction1()); tree2.addTreeExpansionListener(new TreeExpansionAction2()); ScrollPane sPaneLeft = new ScrollPane(); ScrollPane sPaneRight = new ScrollPane(); this.getContentPane().add(sPaneLeft,BorderLayout.WEST); this.getContentPane().add(sPaneRight,BorderLayout.EAST); sPaneLeft.add(tree1); sPaneRight.add(tree2); this.pack(); this.setVisible(true); } class TreeExpansionAction1 implements TreeExpansionListener{ public void treeCollapsed(TreeExpansionEvent event) { TreePath path = event.getPath(); System.out.println("tree 1 collapsed : " + path.toString()); tree2.collapsePath(path); } public void treeExpanded(TreeExpansionEvent event) { TreePath path = event.getPath(); System.out.println("tree 1 expanded : " + path.toString()); tree2.expandPath(path); } } class TreeExpansionAction2 implements TreeExpansionListener{ public void treeCollapsed(TreeExpansionEvent event) { TreePath path = event.getPath(); System.out.println("tree 2 collapsed : " + path.toString()); tree1.collapsePath(path); } public void treeExpanded(TreeExpansionEvent event) { TreePath path = event.getPath(); System.out.println("tree 2 expanded : " + path.toString()); tree1.expandPath(path); } } public static void main(String[] args) { new Tree(); } }
to gtlang78():非也,我是用DefaultTreeModel构造的,这不是问题。 每个结点都是DefaultMutableTreeNode类型,我是写了一个类extends DefaultMutableTreeNode而已。问题是这个model被上传到服务器上,并传入多个客户端,可能问题出在这里。 我也不明白为什么?
拼了
to nielinjie:
repaint我试过,一样没用。to bobokong:
两树的结构完会一样,而且现在问题其实选择的path我已传过去了,因为如果我listen到jTree2的valuechange,弹出当前选择结点路径,是对的!!说明jTree2当前确实选中了这个结点。
只是界面上不能显示出选中结点后的反向显示的样式。
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;public class Learn extends JFrame { JTree tree1 = new JTree();
JTree tree2 = new JTree(); public Learn(){
tree1.addTreeExpansionListener(new TreeExpansionAction1());
tree2.addTreeExpansionListener(new TreeExpansionAction2()); ScrollPane sPaneLeft = new ScrollPane();
ScrollPane sPaneRight = new ScrollPane();
this.getContentPane().add(sPaneLeft,BorderLayout.WEST);
this.getContentPane().add(sPaneRight,BorderLayout.EAST);
sPaneLeft.add(tree1);
sPaneRight.add(tree2);
this.pack();
this.setVisible(true);
} class TreeExpansionAction1 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 collapsed : " + path.toString());
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 expanded : " + path.toString());
int row = tree1.getRowForPath(path);
tree2.expandRow(row);
}
} class TreeExpansionAction2 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 collapsed : " + path.toString());
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 expanded : " + path.toString());
int row = tree2.getRowForPath(path);
tree1.expandRow(row);
}
} public static void main(String[] args) {
new Learn();
}
}
class TreeExpansionAction1 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 collapsed : " + path.toString());
int row = tree1.getRowForPath(path);
tree2.collapseRow(row);
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 expanded : " + path.toString());
int row = tree1.getRowForPath(path);
tree2.expandRow(row);
}
} class TreeExpansionAction2 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 collapsed : " + path.toString());
int row = tree2.getRowForPath(path);
tree1.collapseRow(row);
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 expanded : " + path.toString());
int row = tree2.getRowForPath(path);
tree1.expandRow(row);
}
}
取得TreePath
从TreePath取得当前展开的行
展开另一棵树的该行
这样做的前提:
两棵树始终保持同步,如果有时同步有时不同步这种方法不行
bobokong(寻找编程的乐趣) 给了我提示,不错。我明白了,下面给出方法:我也发现有这个问题。我用setSelectedPath(selPath)就是不行,但用setSelectedRow(selRow)方法倒是可行的。现在我又试了bobokong的展开关闭树的例子,也发现是这样的,用expandRow()可以但用expandPath()就不行,不知道为什么?我解决的方法就是先展开它,这样取得的行号就对应起来了,再用setSelectedRow就可以正确地选中结点了。多谢。明天给分。还希望高手能解释一下为什么setSelectedPath不行,expandPath也不行,看起来好象真得是jTree1的selectPath不能用于jTree2,但是为什么呢?
jTree2.setSelectionModel(model);还有很多其他的Swing组件可以用类似的方法同步,例如JSlider,JProgressBar,JList等
那如何利用同一个选择模型实现两棵树展开的同步呢?
注意构造函数的第一行,将两个tree的model设为相同,以后就很方便的实现了两棵树的同步。
我觉得这种方法才真正解决了sharetop(天生不笨)的问题,建议给gtlang78()加分import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;public class Tree extends JFrame { JTree tree1 = new JTree();
JTree tree2 = new JTree(); public Tree(){
tree2.setModel(tree1.getModel()); tree1.addTreeExpansionListener(new TreeExpansionAction1());
tree2.addTreeExpansionListener(new TreeExpansionAction2()); ScrollPane sPaneLeft = new ScrollPane();
ScrollPane sPaneRight = new ScrollPane();
this.getContentPane().add(sPaneLeft,BorderLayout.WEST);
this.getContentPane().add(sPaneRight,BorderLayout.EAST);
sPaneLeft.add(tree1);
sPaneRight.add(tree2);
this.pack();
this.setVisible(true);
} class TreeExpansionAction1 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 collapsed : " + path.toString());
tree2.collapsePath(path);
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 1 expanded : " + path.toString());
tree2.expandPath(path);
}
} class TreeExpansionAction2 implements TreeExpansionListener{
public void treeCollapsed(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 collapsed : " + path.toString());
tree1.collapsePath(path);
} public void treeExpanded(TreeExpansionEvent event) {
TreePath path = event.getPath();
System.out.println("tree 2 expanded : " + path.toString());
tree1.expandPath(path);
}
} public static void main(String[] args) {
new Tree();
}
}
多谢两位,其实这个问题本身不是这样的。我是想实现网络同步浏览的功能,所以tree的model都是从服务器上取来的同一个model,然后我setModel它们,所以应该是一样的,并不是在一个窗口中有两个tree,我之所以用这个问题来提问是想简化一下问题,便于大家调试。如果设置同样的model,但是界面上只有一个tree,同样从同一个server中取同样一个model构建的。我原来的代码就是这样。似乎仍是不行的。也许这两个model或treepath真得是看上去一样,实质有差别吧。
to gtlang78():非也,我是用DefaultTreeModel构造的,这不是问题。
每个结点都是DefaultMutableTreeNode类型,我是写了一个类extends DefaultMutableTreeNode而已。问题是这个model被上传到服务器上,并传入多个客户端,可能问题出在这里。
我也不明白为什么?
1。将要显示的数据和界面元素分离;
2。将界面无素注册到数据(可封装成类);
3。更新数据时广播给注册的无素。
建议你去读读《DESIGN PATTERN》。这就是该书中提到的OBSERVER模式希望对你有帮助!!