0

这是我对 Swing 的问题:
想象一下带有一个文本字段和一个按钮的框架。在这个框架后面有一个字段的数据类。

  • 文本字段具有 FocusListener,它使用 FocusOut 上的文本字段中的值更新数据类字段
  • 按钮具有 ActionListener,它在单击时将数据类发送到服务器

如果我修改文本字段中的值并立即单击按钮,有时会将具有旧值的数据类发送到服务器。在我看来,不能保证在按钮的 ActionPerformed 事件之前处理文本字段的 FocusOut 事件。如果是这样,有什么方法可以保护它吗?我的意思是一些干净的方式,如果没有必要,我不想把它弄脏。

4

4 回答 4

2

只是为了好玩,用 InputVerifier 实现了一个穷人的单向绑定:注意 inputVerifier 保证在转移焦点之前被访问(并且似乎在当前版本的 jdk 中工作 - 在旧版本中有一些问题),所以只要提交操作中涉及焦点转移,在验证器中进行任何更新都应该是安全的:

验证者和一些粗略的数据对象:

/**
 * Very simple uni-directional binding (component --> data) class.
 */
public static class BindingVerifier extends InputVerifier {

    private RawData data;
    private boolean first;
    public BindingVerifier(RawData data, boolean first) {
        this.data = data;
        this.first = first;
    }


    @Override
    public boolean shouldYieldFocus(JComponent input) {
        String text = ((JTextComponent) input).getText();
        if (first) {
            data.one = text;
        } else {
            data.two = text;
        }
        return true;
    }


    @Override
    public boolean verify(JComponent input) {
        return true;
    }

}

public static class RawData {
    String one;
    String two;
    public RawData(String one, String two) {
        this.one = one;
        this.two = two;
    }

    public String toString() {
        return one + "/" + two;
    }
}

用法:

final RawData data = new RawData(null, null);
JTextField first = new JTextField(20);
first.setInputVerifier(new BindingVerifier(data, true));
JTextField second = new JTextField(20);
second.setInputVerifier(new BindingVerifier(data, false));
Action commit = new AbstractAction("commit") {

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(data);
    }
};
JComponent form = new JPanel();
form.add(first);
form.add(second);
form.add(new JButton(commit));
于 2013-04-10T16:14:19.840 回答
1
  • 在 Swing 中不可能,不可能对来自一个 Listener 的事件进行排序,而不是在两个或多个 Listener 同时触发事件的情况下

如果我修改文本字段中的值并立即单击按钮,有时会将具有旧值的数据类发送到服务器。在我看来,不能保证在按钮的 ActionPerformed 事件之前处理文本字段的 FocusOut 事件。如果是这样,有什么方法可以保护它吗?我的意思是一些干净的方式,如果没有必要,我不想把它弄脏。

  • 焦点是异步的,但在所有情况下都会触发正确的事件,问题可能出在您的代码中

  • 侦听器的某些组合可能会导致无限循环(事件会延迟触发),然后您的控制器可能会触发错误的事件顺序

于 2013-04-10T13:23:28.383 回答
1

你可以这样做。我只给出一个伪代码。

private boolean check = false;

txtField FocusOutMethod {
 check = true;
}

button ActionPerformedMethod(){

 if(check){

      place your code that you want to execute in button click.

      check = false;
 }
}

这样,actionPerformed 方法将仅在 focusOut 方法执行后运行您的代码。

于 2013-04-10T13:05:43.527 回答
1

如果我修改文本字段中的值并立即单击按钮,有时会将具有旧值的数据类发送到服务器。在我看来,不能保证在按钮的 ActionPerformed 事件之前处理文本字段的 FocusOut 事件。如果是这样,有什么方法可以保护它吗?

以不同的方式设计表格。也就是说,当您单击按钮时,ActionListener 应该在表单上的所有文本字段上调用 ​​getText() 方法。

于 2013-04-10T15:42:32.640 回答