2010-12-03 52 views
0

我有一個Java Swing應用程序,它有許多JTextField和一個數據模型。在模型上使用JTextField(在focusLost上)並使用模型數據運行Actions

當離開文本字段(焦點丟失)時,文本被寫入模型。到現在爲止還挺好。

有JMenu-Actions從模型讀取數據並將其發送到服務器。

問題是,當它的加速器運行菜單動作時,不會觸發「焦點丟失」。所以動作讀取並傳輸來自數據模型的舊值。 。

可能有很多方法可以解決這個問題......?你有建議如何解決這個問題?

什麼不爲我工作:

  • 寫上每一個按鍵進行建模(通過文檔偵聽):不使用,應該只留下寫文本框(焦點丟失)。文本在寫入模型之後(昂貴)評估 - 每次按鍵後都無法運行。
  • 在每個動作中處理寫作模型。有約。 500個Textfields和ca. 100項行動。在不忘記任何事情的情況下進行比賽。

Runnable的演示代碼:

package swingmodel; 

import java.awt.FlowLayout; 
import java.awt.event.*; 

import javax.swing.*; 

/** 
* Simple Demo Problem. Enter a Text in the first Textfield and press ALT-T. The 
* focus listener did no run, therefore the old value from model is displayed. 
*/ 
public class TextDemoOnMenu extends JPanel { 
    private Model model; 

    public TextDemoOnMenu() { 
    super(new FlowLayout()); 

    model = new Model(); 
    MyTextField textField = new MyTextField(20, model); 
    add(textField); 
    add(new JTextField(5)); 

    } 

    class MyTextField extends JTextField { 

    private Model model; 

    public MyTextField(int arg, Model model) { 
     super(arg); 
     this.model = model; 
     addFocusListener(new FocusAdapter() { 
     @Override 
     public void focusLost(FocusEvent e) { 
      System.out.println("focus lost"); 
      writeToModel(); 
     } 
     }); 
    } 

    public void writeToModel() { 
     this.model.setText(getText()); 
    } 
    } 

    class ShowModelTextAction extends AbstractAction { 

    public ShowModelTextAction(String string) { 
     super(string); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     String message = "text is: " + model.getText(); 
     JOptionPane.showMessageDialog(TextDemoOnMenu.this, message); 
    } 
    } 

    class Model { 
    private String text; 

    void setText(String t) { 
     text = t; 
    } 

    public String getText() { 
     return text; 
    } 
    } 

    private void createAndShowGUI() { 
    // Create and set up the window. 
    JFrame frame = new JFrame("TextDemo"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    // Add contents to the window. 
    frame.add(this); 

    Action action = new ShowModelTextAction("show text"); 
    JMenuBar menuBar = new JMenuBar(); 
    JMenu menu = new JMenu("My Menu"); 
    menuBar.add(menu); 
    JMenuItem menuItem = new JMenuItem("show text"); 
    menuItem.setAction(action); 
    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.ALT_MASK)); 
    menu.add(menuItem); 
    frame.setJMenuBar(menuBar); 

    // Display the window. 
    frame.setSize(400, 200); 
    frame.setVisible(true); 
    } 


    public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     new TextDemoOnMenu().createAndShowGUI(); 
     } 
    }); 
    } 

} 

回答

2

您可以修改所有操作以使用KeyboardFocusManager。你會得到當前有焦點的組件。如果它是您的自定義文本字段之一,那麼您可以在處理該動作之前強制更新模型。

的文本(貴),將其寫入到模型

而且,這聽起來像你應該處理focusGained以及後評估。然後可以保存原始文本,並在自動更新模型之前對丟失焦點的文本進行比較。 (也就是說,如果有人只是瀏覽所有文本字段?)。

+0

謝謝,這有幫助! ;) – Synox 2011-01-28 09:42:27

1

每個文本字段創建一個骯髒的標誌。如果發生保存事件,則可以使用任何髒的文本字段來更新模型。

如果您擔心您會忘記爲特定文本字段執行此操作,那麼您對文本字段的管理就是問題所在。你應該有一個工廠方法,它們可以正確設置它們併爲它們創建髒標誌。

我的另一個建議是,如果發生該保存操作,請求將焦點置於隱藏組件上以觸發textField上的focusLost。保存完成後,您將焦點返回給以前的所有者。

相關問題