0

我目前正在研究我们小组第一学期考试项目的 GUI 部分,我遇到了一个关于回调和事件处理的奇怪问题。

有点跑题了:我已经用谷歌搜索了这个,但是真的没有找到在 Java 中使用回调的任何具体例子,所以从我收集的内容来看......根据定义......我在这里做的实际上是一个回调(如果你能解释原因会很棒,或者指向一个详细解释它的页面)

这是代码:

private FocusListener callback = new FocusListener(){
    @Override public void focusGained(FocusEvent e){
        if(hasBeenSet){}else{tfield.setText("");hasBeenSet=true;}
    } @Override public void focusLost(FocusEvent e){}};

    ...

    tfield = new JTextField("Insert CPR number", 8);
    constraint.gridx = 0;
    constraint.gridy = 1;
    constraint.gridwidth = 2;
    panel.add(tfield, constraint);

            tfield.addFocusListener(callback);

    tfield = new JTextField("Type new password", 8);
    constraint.gridx = 0;
    constraint.gridy = 2;
    panel.add(tfield, constraint);

            tfield.addFocusListener(callback);

    tfield = new JTextField("Retype new password", 8);
    constraint.gridx = 0;
    constraint.gridy = 3;
    panel.add(tfield, constraint);

            tfield.addFocusListener(callback);

当我启动 GUI 时,它具有这三 (3) 个文本字段,其想法是在用户关注文本字段时删除文本。这应该适用于所有三个文本字段,但显然,无论您单击什么文本字段,只有最后一个文本字段被设置为空字符串。我对此非常好奇,因为每个对象都是单独实例化的。

这里明显的解决方法是将 tfield 重命名为喜欢“tfield [1-3]”,但如果你能用这个来幽默我会很棒:)

另外:请注意,所有的 GUI 代码实际上都在构造函数中。是的,我知道这完全是荒谬的,但我们的设计表明所有逻辑和数据处理都将在构造函数完成后发生......所以这里不应该有任何威胁,但我不知道这是否会以某种方式与 FocusListener 的回调方法发生冲突。

谢谢你。:)

PS 对于“重新/键入新密码”字段,我确实承认 JComponent JPasswordField,并且在此问题修复后将更改。所以不需要安全警告:)

4

1 回答 1

2

tfield变量保存对 的最后一个实例的引用JTextField。做你想做的事情是这样的:

private FocusListener callback = new FocusListener() {
    @Override public void focusGained(FocusEvent e){
        JTextField jtf = (JTextField) e.getSource();
        if(hasBeenSet){}else{jtf.setText("");hasBeenSet=true;}
    }
    ...

注意:当您的代码读取时,hasBeenSet将在所有 3 个文本字段中共享。

更新:

Java 不支持闭包,因此在focusGained运行时,它会看到 的最后一个值tfield,而不是tfield安装侦听器时的值。

它看起来hasBeenSet被定义为外部类的成员,因此focusGained正在检查所有 3 个文本字段的相同变量。这是一种处理我认为您正在尝试做的事情的方法:

tfield = new JTextField("Insert CPR number", 8);
tfield.putClientProperty("originalText", tfield.getText());

然后在焦点上获得了:

    @Override public void focusGained(FocusEvent e){
        JTextField jtf = (JTextField) e.getSource();
        if(jtf.getClientProperty("originalText").equals(jtf.getText())){
             jtf.setText("");
        }
    }

这些putClientProperty/getClientProperty方法是在JComponent类中定义的,因此这些方法在每个从JComponent. 他们存储/检索Object给定的字符串。在这种情况下,字符串“originalText”包含最初用于初始化JTextField. 获得焦点后,如果该字段仍包含该值,则将其设置为空白。同样,您可以执行类似的操作focusLost,如果该字段为空白,则将其设置为为“originalText”检索的值。

于 2012-05-24T17:46:51.850 回答