1

我有一个 JTree,其中树的每个节点都代表一些用户数据。数据是可编辑的,并存储在文件/db 中。有一堆 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。

如何保存此用户数据?我将不胜感激任何帮助/指针。

谢谢!

4

1 回答 1

2

因为 JTree 事件的 valueChanged 发生在 JTextField 的 focusLost 之前。

  • 这是合乎逻辑的顺序,不要改变它,一个JComponents focusGained,然后focusLost在窗口焦点中的焦点所有者之后

  • Focus是相当异步的,因为JTextComponent可以延迟从添加触发的事件Listeners/InputMask/Formatter,可以通过延迟来解决invokeLater,忘记了,不是你的问题

  • (我...)从 中删除TreeSelectionListenerJTextField移至(逻辑)JTree

  • 添加System.out.println(getText());,作为第一行代码public void valueChanged(TreeSelectionEvent e) {,看看发生了什么:-),有存储的地方(使用Runnable#ThreadSwingWorker将任何内容重定向到Workers Thread

  • 那么如果 JTextField 中的值发生更改并且用户单击同一个节点,然后值保持不变或 JComponent 用原始值刷新,那么会发生什么问题,但这是关于业务逻辑,而不是关于如何编码,我的猜测

于 2013-05-20T06:40:56.990 回答