多くの JTextField とデータモデルを持つ Java Swing アプリケーションがあります。
テキストフィールドを離れる (フォーカスが失われる) と、テキストがモデルに書き込まれます。ここまでは順調ですね。
モデルからデータを読み取り、それをサーバーに送信する JMenu アクションがあります。
問題は、アクセラレータによってメニュー アクションを実行するときに「フォーカスが失われた」が発生しないことです。そのため、アクションはデータモデルから古い値を読み取って送信します。.
これを修正する方法はたくさんあるかもしれません...?これを解決する方法について提案はありますか?
私にとってうまくいかないこと:
- キーを押すたびにモデルに書き込む (ドキュメント リスナー経由): 使用できません。テキスト フィールドを離れるときにのみ書き込む必要があります (フォーカスが失われます)。テキストは、モデルに書き込んだ後に (高価に) 評価されます。キーを押すたびに実行することはできません。
- すべてのアクションでモデルへの書き込みを処理します。そこに約。500のテキストフィールドと約。100アクション。何もかも忘れずに合わせるのは難しい。
実行可能なデモ コード:
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();
}
});
}
}