java - 将 JTextField 与模型结合使用(在 focusLost 上)并使用模型数据运行操作

标签 java swing jtextfield

我有一个 Java Swing 应用程序,它有许多 JTextField 和一个数据模型。

离开文本字段(焦点丢失)时,文本将写入模型。到目前为止,一切顺利。

有 JMenu-Actions 从模型读取数据并将其发送到服务器。

问题是,当通过加速器运行菜单操作时,不会触发“焦点丢失”。因此,操作从数据模型中读取并传输旧值。 .

可能有很多方法可以解决这个问题...?您对如何解决这个问题有建议吗?

什么对我不起作用:

  • 每次按键时写入模型(通过文档监听器):不可用,只能在离开文本字段时写入(焦点丢失)。文本在写入模型后会进行(昂贵的)评估 - 每次按键后无法运行。
  • 在每个 Action 中处理模型的写入。大约有。 500 个文本字段和大约。 100 个 Action 。很难匹配而不忘记任何东西。
<小时/>

可运行的演示代码:

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();
      }
    });
  }

}

最佳答案

您可以修改所有操作以使用 KeyboardFocusManager。您将获得当前具有焦点的组件。如果它是您的自定义文本字段之一,那么您可以在处理操作之前强制更新模型。

The text is (expensively) evaluated after writing it to the model

此外,听起来您也应该处理 focusGained 。然后可以保存原始文本并在自动更新模型之前对失去焦点的文本进行比较。 (即,如果有人只是按 Tab 键浏览所有文本字段怎么办?)。

关于java - 将 JTextField 与模型结合使用(在 focusLost 上)并使用模型数据运行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4344843/

相关文章:

java - 从作为几个局部变量之一的 JTextField 获取数据

Java Swing TitledBorder 自定义颜色

java - 具有使用 Swing 输入的文本字段的 GUI

java - 接受正则表达式并生成 NFA (Java)

java - 如何使用单选按钮根据用户输入执行不同的方程?

java - 更改 JLabel 的文本 - 初学者

java - 返回类型之前泛型的目的是什么

java - 从方法中收到错误的颜色

java - 如何访问按钮的每个单独的 ActionPerformed?

java - 此处不允许使用“void”类型 - 参数的监听器