2013-05-20 21 views
1

我有一個JTree,其中樹的每個節點代表一些用戶數據。數據是可編輯的並存儲在文件/數據庫中。有一堆JTextField可以讓你編輯/更新節點的用戶數據。當JTextField失去焦點時,保存數據事件。除非在JTree中更改節點的選擇,否則這可以正常工作。因爲JTree事件的valueChanged發生在JTextField的focusLost之前。JTree valueChanged事件在單擊節點時調用另一個組件的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

在此處發佈代碼,而不是在pastebin上。 – camickr

+0

它長時間粘貼在這裏。我認爲這樣做會很不方便,因爲有時會讓問題難以閱讀。 – Mo3z

回答

2

因爲JTree事件的valueChanged發生在 JTextField的focusLost之前。

  • 這是邏輯順序,不改變這種狀況,一個JComponents focusGained,然後在窗口焦點所有者focusLost在對焦後

  • Focus相當asyncronous,爲JTextComponent可延遲事件發自新增Listeners/InputMask/Formatter,可以通過延遲解決invokeLater,忘了那個,不是你的問題

  • (我是...)刪除TreeSelectionListenerJTextField,移動到(邏輯)JTree

  • 添加System.out.println(getText());,爲第1碼線public void valueChanged(TreeSelectionEvent e) {,看什麼:-) happend,有地方存放(使用Runnable#ThreadSwingWorker重定向到任何Workers Thread

  • 然後,這裏仍然存在問題最新情況如果值在JTextField中更改並且用戶單擊到同一個節點,則值保持不變或JComponent用原始值刷新,但這是關於bussines邏輯,而不是關於如何編碼,我的猜測

+0

1.事件的順序是 - > JTree.valueChanged> JTextField.focusLost> JTree.focusGained。如何在沒有獲得焦點的情況下爲JTree創建valueChange?也許,我沒有跟隨。 2. TreeSelectionListener實際上是在應用程序中的JTree,只是把SSCCE放在一起,我把它放在JTextField中。你能解釋一下嗎?我確實得到了我需要的文本,但是我失去了選擇,即節點。 4.如果我解決了jtextField的focusLost始終在JTree中的任何內容之前被觸發的問題,它將解決問題。 – Mo3z

+0

not focusLost可以從focusGained初始化,然後JTrees選擇引起focusGained,請不要改變事件順序,cand be fragille,breakable,(因爲)我相信可以爲兩個JComponents創建代碼來交換焦點在Window中,理論是在我的文章中,Focus以編程方式添加到添加到util的JComponents中。列表中,不要思考,因爲不知道,在添加DocumentListener(Filter),inputmask,formatter時發生了什麼,導致JComboBox&JSpinner和JTextField的長循環 – mKorbel

+0

得到它謝謝! – Mo3z

相關問題