我目前正在研究小组第一个学期考试项目的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的回调方法冲突。

谢谢。 :)

附言对于“重新输入新密码”字段,我确实确认了JComponent JPasswordField,并且在解决此问题后将对其进行更改。因此,不需要安全警告:)

最佳答案

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的最后一个值,而不是安装listerner时具有的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继承的每个Swing GUI组件中都可用。他们存储/获取给定字符串的Object。在这种情况下,字符串“ originalText”保存最初用于初始化JTextField的值。获得焦点后,如果该字段仍包含该值,则将其设置为空白。同样,您可以在focusLost中执行类似的操作,如果该字段为空白,则将其设置为为“ originalText”检索的值。

关于java - FocusListener回调方法不适用于来自同一变量的单独实例化的对象吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10742567/

10-09 20:33