【问题标题】:How to "ignore/discard" Swing UI events when doing data validations on UI?在 UI 上进行数据验证时如何“忽略/丢弃”Swing UI 事件?
【发布时间】:2013-03-28 09:04:17
【问题描述】:

有一个文本字段,当失去焦点时,它将验证输入,如果未通过,则打印出错误消息(简单来说这里只有一个空检查)。在文本字段旁边有一个按钮,单击它会打印出文本。

正如我所尝试的,当输入一些文本然后单击按钮时,它将触发文本字段的焦点丢失事件和按钮事件。换句话说,它会先进行验证,然后将输入的文本打印出来。

我的问题来了,如果验证未通过,防止打印出文本的好方法是什么?或者如果验证未通过,有没有办法“忽略”按钮上的点击事件?

我尝试使用指示验证结果的布尔标志并在执行按钮操作时检查标志,但我认为这不是一个好方法。我知道 Swing 中有一个事件调度程序线程来处理事件,我可以从这里取消事件吗?

下面是解释问题的一段代码:

public class SimpleDemo
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel content = new JPanel(new FlowLayout());
        frame.setContentPane(content);

        final JTextField textField = new JTextField(10);
        textField.addFocusListener(new FocusAdapter()
        {
             @Override
             public void focusLost(FocusEvent e)
             {
                 String text = textField.getText();
                 // do some validation here, if not validated 
                 // do not trigger the event on button.
                 if ("".equals(text))
                 {
                     System.out.print("please input a text!");
                 }
             }
        });
        content.add(textField);

        JButton button = new JButton("Print Text");
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                // action performed for button
                String text = textField.getText();
                System.out.println(text);
            }
        });
        content.add(button);

        frame.setVisible(true);
        frame.pack();
    }
}

【问题讨论】:

  • 考虑使用 InputVerifier(而不是低级 focusListener)-validation example
  • @kleopatra 我尝试了 InputVerifier,但显示错误消息后按钮似乎无法弹起,您能检查我的最新代码并提供建议吗?
  • 之前没有看到您的非答案(这是您不应该在答案部分中对您的问题进行澄清/跟进的另一个原因 :-)。修复 InputVerifier 的实现并检查按钮是否仍然卡住(早期的 jdks 中存在错误,因此可能)
  • 对于example

标签: java swing


【解决方案1】:

我在处理应用程序时遇到了类似的问题。我像下面这样解决了 我创建了一个抽象类ApplicationFrame,应用程序中的每一帧都扩展了它

public abstract class ApplicationFrame extends JFrame implements ActionListener {
    @Override
    final public void actionPerformed(ActionEvent event) {
        if(validateInput()){
             performAction(event);
        }
    }

    /*
    * Sub class should override this method to receive any action
    */
    protected void performAction(ActionEvent event) {};

    /*
     * Sub class should override this method to perform validation
    */
    abstract protected boolean validateInput();
}

现在所有框架都将扩展此基础框架,如下所示:

public class Frame1 extends ApplicationFrame{
    @Override
    protected void performAction(ActionEvent event) {
        // perform action
    }
    @Override
    protected boolean validateInput() {
        // return true or false depending upon the validation results
    }
    // if you want to add Action Listener, you need to add like this:
    btnSomeButton.addActionListener(this);
}

如果你需要处理Focus事件,你可以使ApplicationFrame或者基础框架实现FocusListener。 这是我解决问题的自定义实现,希望对您有所帮助。

【讨论】:

    【解决方案2】:
    • 在启动时禁用按钮
    • 失去焦点后,仅在输入通过验证时验证文本和启用按钮。
    • 开始文本更改时,禁用按钮

    【讨论】:

      【解决方案3】:

      让用户界面与用户交流总是有意义的。因此,当用户未输入任何内容时,您可以将“请输入文本”显示为 textField 的默认文本。 这是此类自定义文本字段的代码:

      public class TextFieldWithDefaultText extends JTextField implements FocusListener{
      
      private final String hint;
      
      public TextFieldWithDefaultText (String $text)
      {
          super($text);
          this.hint = $text;
          addFocusListener(this);
      }
      
      @Override
      public void focusGained (FocusEvent $e)
      {
          if (this.getText().isEmpty())
          {
              super.setText("");
          }
      }
      
      @Override
      public void focusLost (FocusEvent $e)
      {
          if (this.getText().isEmpty())
          {
              super.setText(hint);
          }
      }
      
      @Override
      public String getText ()
      {
          String typed = super.getText();
          return typed.equals(hint) ? "" : typed;
      }
      

      }

      为您的按钮编写 actionListerner,如下所示:

      JButton button = new JButton("Print Text");
          button.addActionListener(new ActionListener()
          {
              @Override
              public void actionPerformed(ActionEvent e)
              {
                  if(!textField.getText().isEmpty())
                      System.out.println(textField.getText());
              }
          });
      

      你的 textField 实现应该是:

      final TextFieldWithDefaultText textField = new TextFieldWithDefaultText ("please input a text");
      

      希望这会有所帮助:)

      【讨论】:

      • 感谢您的回答。我同意你的看法,但困扰我的问题是如何“忽略”这些事件。 :)
      • 实际上我通过检查 if(!textField.getText().isEmpty()) 的条件来忽略该事件。但是如果要完全避免将事件传递给java eventQueue,恐怕是不可能的。 UI 的手动事件处理是使用 Java 本机对等点完成的。因此,如果您想忽略它,请检查 actionPerformed() 方法中的条件。我知道这是一种 hack :)
      • 如果您认为它回答了您的问题,请不要忘记选择它作为答案:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      相关资源
      最近更新 更多