2010-12-03 10 views
0

私はJava Swingアプリケーションを使用しています.JTextFieldとデータモデルがたくさんあります。モデルでJTextFieldを使用する(focusLostで)モデルデータでアクションを実行する

テキストフィールドを離れると(フォーカスが失われる)、テキストがモデルに書き込まれます。ここまでは順調ですね。

モデルからデータを読み取り、それをサーバーに送信するJMenu-Actionsがあります。

問題は、アクセラレータでメニューアクションを実行しているときに「フォーカスが失われません」が発生していないということです。したがって、アクションはデータモデルから古い値を読み取り、送信します。 。

これを修正する方法はたくさんありますか? の提案これを解決する方法はありますか?

何私のために動作しません:(ドキュメントリスナーを経由して)すべてのキーを押すにモデル化する

  • 書き込み:使用できない、唯一の(フォーカスが失われた)テキストフィールドを離れる際に書く必要があります。テキストはモデルに書き込んだ後に(高価に)評価されます。キーを押すたびに実行することはできません。
  • すべてのアクションでモデルへの書き込みを処理する。そこにca. 500のテキストフィールドと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を使用するようにすべてのアクションを変更できます。フォーカスを持っている現在のコンポーネントを取得します。カスタムテキストフィールドの1つであれば、アクションを処理する前にモデルを強制的に更新することができます。テキスト(ぜいたく)モデル

にそれを書き込んだ後に評価される

あなたが同様のfocusGainedハンドリングしなければならないように。また、それが聞こえます。次に、元のテキストを保存し、フォーカスを失ったテキストを比較してモデルを自動的に更新します。 (つまり、誰かがすべてのテキストフィールドをタブするだけの場合はどうなりますか?)

+0

ありがとう、これが手伝ってくれました! ;) – Synox

1

各TextFieldにダーティフラグを作成します。 saveイベントが発生した場合は、モデルをダーティなtextFieldで更新できます。

特定のtextFieldでこれを行うことを「忘れる」と心配しているのであれば、問題のテキストフィールドを管理することになります。それらを正しく設定し、汚れたフラグを作成するためのファクトリメソッドを用意する必要があります。

私の他の提案は、その保存アクションが発生したときに、隠しコンポーネントにフォーカスを要求して、textFieldでfocusLostをトリガーすることです。保存が完了すると、前の所有者にフォーカスが戻されます。

関連する問題