1

ツリーの各ノードがユーザー データを表す 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;
        }      
}

この例では 1 つのフィールドしかありませんが、実際のアプリケーションでは、ユーザー データを表す複数のフィールドがあります。また、JTextField は単なる例であり、入力フィールドは JComboBox または JSpinner である可能性があります。

このユーザーデータを保存するにはどうすればよいですか? ヘルプ/ポインタをいただければ幸いです。

ありがとう!

4

1 に答える 1

2

JTree イベントの valueChanged は、JTextField の focusLost の前に発生するためです。

  • これは論理的な順序付けです。1 つ変更しないでください。次に、Focus in Window のJComponents focusGained所有者をフォーカスした後focusLost

  • Focusは非常に非同期です。なぜなら、JTextComponent追加されたイベントの発火が遅れる可能性があるためListeners/InputMask/FormatterですinvokeLater

  • (I'm ...)TreeSelectionListenerから削除JTextField、 (論理) に移動JTree

  • System.out.println(getText());を最初のコード行としてに追加し、何が起こったかを確認しpublic void valueChanged(TreeSelectionEvent e) {てください :-)、保存する場所があります ( を使用Runnable#ThreadSwingWorkerて にリダイレクトしますWorkers Thread)

  • 次に、値がJTextFieldで変更され、ユーザーが同じノードをクリックするとどうなるかという疑問が残ります。その後、値は変更されないか、JComponentが元の値で更新されますが、これはビジネスロジックに関するものであり、コーディング方法に関するものではありません.

于 2013-05-20T06:40:56.990 に答える