【问题标题】:How to wait for JOptionPane to be closed before dispatching any more events如何在调度更多事件之前等待 JOptionPane 关闭
【发布时间】:2012-06-18 21:36:43
【问题描述】:

我有几个文本字段,我在它们之间切换。在focusLost(),我正在打开JOptionPane。我希望focusGained() 中的代码在JOptionPane 关闭后执行。即使对话框是模态的,focusGained() 也会在 JOptionPane 关闭之前被调用。有没有办法解决?

发现this similar question,但似乎也没有解决。 Postpone Event Queue after Focus Lost

这是一个代码示例。您会注意到在 JOptionPane 关闭之前打印了“Focus Gained”。

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class ShortTest implements FocusListener
{
private void go()
{
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    JTextField text1 = new JTextField();
    text1.setName("text1");
    text1.addFocusListener(this);

    JTextField text2 = new JTextField();
    text2.setName("text2");
    text2.addFocusListener(this);

    panel.add(new JLabel("tex1"));
    panel.add(text1);

    panel.add(new JLabel("text2"));
    panel.add(text2);

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

public static void main(String [] args)
{
    ShortTest test = new ShortTest();
    test.go();
}

@Override
public void focusGained(FocusEvent e)
{
    if (!e.isTemporary() && (e.getSource() instanceof JTextField))
    {
        System.out.println("Focus Gained: " + ((JTextField)e.getSource()).getName());
    }
}

@Override
public void focusLost(FocusEvent e)
{
    if (!e.isTemporary() && (e.getSource() instanceof JTextField))
    {
        JOptionPane.showOptionDialog(null, ((JTextField)e.getSource()).getName() + " lost focus", "Title", JOptionPane.DEFAULT_OPTION, 0, null, null, null);
    }
}
}

【问题讨论】:

  • 考虑创建并发布一个SSCCE,我们可以运行和修改它并展示您的问题。
  • 查看我的答案的编辑。 1+ 用于发布 sscce - 非常令人印象深刻!

标签: java swing overriding joptionpane event-dispatch-thread


【解决方案1】:

也许您想要的不是焦点侦听器(非常低级的构造),而是输入验证器(更高级别的构造)。这应该在焦点转移之前做出响应。例如,在下面的代码中,如果用户尝试在文本字段中输入非数字数据,验证器会做出反应。是的,这也可以使用 DocumentFilter 来完成。

import javax.swing.*;

public class VerifierEg extends JPanel {
   private static final int FIELD_COUNT = 3;

   public VerifierEg() {
      InputVerifier inputVerifier = new InputVerifier() {

         @Override
         public boolean verify(JComponent input) {
            final JTextField textField = (JTextField) input;
            String text = textField.getText();
            for (char c : text.toCharArray()) {
               if (!Character.isDigit(c)) {
                  textField.setText("");
                  JOptionPane.showMessageDialog(VerifierEg.this, "Text: \""
                        + text + "\" must hold only digits", "Text Field Error",
                        JOptionPane.ERROR_MESSAGE);
                  return false;
               }
            }
            return true;
         }
      };
      for (int i = 0; i < FIELD_COUNT; i++) {
         JTextField field = new JTextField(6);

         field.setInputVerifier(inputVerifier);
         add(field);
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Enter Numbers");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new VerifierEg());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

编辑:
InputVerifier 可以用于您的目的,即使您没有以任何特定方式验证输入。例如,要修改您的代码:

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BoxLayout;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class ShortTest2 {
   private void go() {
      final JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JPanel panel = new JPanel();
      panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

      InputVerifier inputVerifier = new InputVerifier() {

         @Override
         public boolean verify(JComponent input) {
            JOptionPane.showMessageDialog(frame,
                  "Focus Lost on " + input.getName());
            return true;
         }
      };

      FocusListener focusListener = new FocusListener() {

         @Override
         public void focusLost(FocusEvent e) {
            String name = ((JComponent)e.getSource()).getName();
            System.out.println("Focus Lost: " + name );
         }

         @Override
         public void focusGained(FocusEvent e) {
            String name = ((JComponent)e.getSource()).getName();
            System.out.println("Focus Gained: " + name );
         }
      };

      JTextField[] textFields = new JTextField[2];
      for (int i = 0; i < textFields.length; i++) {
         JTextField textField = new JTextField(10);
         String name = "text " + (i + 1);
         textField.setName(name);
         textField.setInputVerifier(inputVerifier);
         textField.addFocusListener(focusListener);

         panel.add(new JLabel(name));
         panel.add(textField);         
      }

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

   public static void main(String[] args) {
      ShortTest2 test = new ShortTest2();
      test.go();
   }
}

顺便说一句,您的 SSCCE 1+!

【讨论】:

  • 感谢您的帮助和建议。虽然我确实需要在焦点事件(以及鼠标事件和 EDT 上的其他时间)期间使用 JOptionPane,但这可能对其他人有所帮助。简而言之,focusGained() 和 focusLost() 都在修改同一个变量,但我没想到 focusGained() 会在 focusLost() 返回之前更改它。我最初认为解决方案是确保在输入 focusGained() 之前返回 focusLost,但最终我只是在 focusGained() 的开头保存了变量的副本,并在 focusGained() 完成时将该副本放回去。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 2016-05-31
  • 1970-01-01
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多