我有一个JTree,其中树的每个节点代表一些用户数据。数据是可编辑的,存储在文件/数据库中。有一堆JTextField允许您编辑/更新节点的用户数据。当JTextField失去焦点时,将触发保存数据事件。除了更改JTree中节点的选择外,这种方法很好。因为JTree事件的valueChanged发生在JTextField的focusLost之前。
以下是SSCCE:http://pastebin.com/wH1Veqdc
public class JTreeFocusTest extends JFrame{
private static final long serialVersionUID = 1L;
public JTreeFocusTest() {
super("JTree Focus Test");
JPanel panel = new JPanel(true);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
MyTree tree = new MyTree();
panel.add(tree);
panel.add(Box.createVerticalStrut(20));
panel.add(new MyTextField(tree));
panel.add(Box.createVerticalStrut(20));
panel.add(new JTextField(30));
getContentPane().add(panel);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
public static void main(String[] args){
new JTreeFocusTest();
}
}
class MyTree extends JTree{
private static final long serialVersionUID = 1L;
public MyTree() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("Root", "Root"));
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(new MyNode("Child 1", "DOC122122"));
root.add(child1);
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(new MyNode("Child 2", "DOC134342"));
root.add(child2);
DefaultTreeModel model = new DefaultTreeModel(root, true);
setModel(model);
getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
setSelectionPath(getPathForRow(0));
}
}
class MyTextField extends JTextField implements FocusListener, TreeSelectionListener{
private static final long serialVersionUID = 1L;
private MyTree tree;
public MyTextField(MyTree tree) {
this.tree = tree;
setText("Some");
addFocusListener(this);
this.tree.addTreeSelectionListener(this);
Dimension dim = new Dimension(200, 20);
setPreferredSize(dim);
setMaximumSize(dim);
setMinimumSize(dim);
}
@Override
public void focusGained(FocusEvent e) {System.out.println("TextField gained focus");}
@Override
public void focusLost(FocusEvent e) {
getSelectedNodeUserObj().setValue(getText());
}
@Override
public void valueChanged(TreeSelectionEvent e) {
setText(getSelectedNodeUserObj().getValue());
}
private MyNode getSelectedNodeUserObj(){
return ((MyNode)((DefaultMutableTreeNode)this.tree.getSelectionPath().getLastPathComponent()).getUserObject());
}
}
class MyNode{
private String label = "";
private String value = "";
public MyNode(String label, String value) {
this.label = label;
this.value = value;
}
public void setValue(String value){
this.value = value;
}
public String getValue(){
return value;
}
public String toString(){
return label;
}
}
在这个例子中,我只有一个字段,但在实际应用程序中,我有几个表示用户数据的字段。另外JTextField只是一个例子,输入字段可以是JComboBox或JSpinner。
如何保存此用户数据?我很感激任何帮助/指针。
谢谢!
答案 0 :(得分:2)
因为JTree事件的valueChanged发生在focusLost之前 JTextField中。
这是逻辑排序,不要改变它,一个JComponents focusGained
,然后在焦点所有者focusLost
之后的焦点在窗口中
Focus
完全异常,因为JTextComponent
可以通过添加Listeners/InputMask/Formatter
触发延迟事件,可以通过延迟invokeLater
来解决,忘了这一点,不是你的问题
(我......)从TreeSelectionListener
移除JTextField
,移至(逻辑)JTree
,
添加System.out.println(getText());
,作为public void valueChanged(TreeSelectionEvent e) {
的第一个代码行,看看发生了什么:-),有存放的地方(使用Runnable#Thread
,SwingWorker
来将任何内容重定向到Workers Thread
)
然后问题是如果在JTextField中更改值并且用户单击到同一节点,然后值保持不变或JComponent用原始值刷新,则会发生什么问题,但这是关于bussines逻辑,而不是关于如何编码,我的推测