Использование JTextField с моделью (on focusLost) и запуск действий с данными модели - PullRequest
0 голосов
/ 03 декабря 2010

У меня есть приложение на Java Swing, в котором есть много JTextFields и модель данных.

При выходе из текстовых полей (фокус потерян) текст записывается в модель.Пока все хорошо.

Существуют JMenu-Actions, которые считывают данные из модели и отправляют их на сервер.

Проблема в том, что «потерянный фокус» не срабатывает при выполнении действия меню с помощью его ускорителя.Таким образом, Действия считывают и передают старое значение из модели данных..

Может быть много способов это исправить ...?У вас есть предложения как это решить?

Что не работает для меня:

  • Запись в модель при каждом нажатии клавиши (через прослушиватель документов): не используется, следует писать только при выходе из текстового поля (фокус потерян).Текст (дорого) оценивается после записи его в модель - не может работать после каждого нажатия клавиши.
  • Обработка записи в модели в каждом действии.Там ок.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();
      }
    });
  }

}

Ответы [ 2 ]

2 голосов
/ 03 декабря 2010

Вы можете изменить все свои Действия, чтобы использовать KeyboardFocusManager. Вы получите текущий компонент, который имеет фокус. Если это одно из ваших пользовательских текстовых полей, вы можете принудительно обновить модель перед обработкой действия.

Текст (дорого) оценивается после записи в модель

Кроме того, звучит так, как будто вы должны обрабатывать focusGained. Затем можно сохранить исходный текст и сделать сравнение текста на потерянном фокусе перед автоматическим обновлением модели. (то есть, что, если кто-то просто просматривает все текстовые поля?).

1 голос
/ 03 декабря 2010

Создать грязный флаг для каждого textField.Если происходит событие сохранения, вы можете обновить модель с любым грязным textField.

Если вы беспокоитесь, что вы «забудете» сделать это для определенного textField, это ваше управление текстовыми полями, которое являетсяпроблема.У вас должен быть фабричный метод для них, который устанавливает их правильно и создает для них грязные флаги.

Мое другое предложение заключается в том, что когда происходит это действие сохранения, вы запрашиваете фокус на скрытом компоненте, чтобы вызвать focusLost на textField,Когда сохранение завершено, вы возвращаете фокус предыдущему владельцу.

...