在JComboBox选择之后打开具有焦点的JOptionPane

时间:2013-07-03 15:29:28

标签: java swing jcombobox joptionpane

我遇到了JComboBoxJOptionPane对话框的问题。 情况是这样的:

  • 它需要从Dialog而不是Frame
  • 运行
  • 在设置数据之前,不需要进行检查
  • 设置数据后,需要对更改进行验证

我有一个包含初始数据的JComboBox,我有一个ActionListener,在选择时会显示一个JOptionPane对话框,其中包含有关重新验证的警告。

当进行选择时,对话框显示为正常但JComboBox未完成循环并保持JComboBox打开,直到单击对话框,然后您需要再次单击以执行选择一个选项(无论第一次点击是否在按钮顶部)。

 import javax.swing.JPanel;
 import java.awt.Frame;
 import java.awt.BorderLayout;
 import javax.swing.JDialog;
 import javax.swing.JComboBox;
 import javax.swing.JOptionPane;
 import javax.swing.UIManager;
 import javax.swing.UnsupportedLookAndFeelException;

 public class DialogFocus extends JDialog {

      private static final long serialVersionUID = 1L;
      private JPanel jContentPane = null;
      private JComboBox jComboBox = null;

      public static void main(String[] args) {
           new DialogFocus(null);
      }

      /**
       * @param owner
       */
      public DialogFocus(Frame owner) {
           super(owner);
           initialize();
           setLookAndFeel();
           this.setVisible(true);
      }

      public void setLookAndFeel() {
           try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
           } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           } catch (UnsupportedLookAndFeelException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           }
      }

      /**
       * This method initializes this
       * 
       * @return void
       */
      private void initialize() {
           this.setSize(300, 200);
           this.setContentPane(getJContentPane());
      }

      /**
       * This method initializes jContentPane
       * 
       * @return javax.swing.JPanel
       */
      private JPanel getJContentPane() {
           if (jContentPane == null) {
                jContentPane = new JPanel();
                jContentPane.setLayout(new BorderLayout());
                jContentPane.add(getJComboBox(), BorderLayout.CENTER);
           }
           return jContentPane;
      }

      /**
       * This method initializes jComboBox     
       *      
       * @return javax.swing.JComboBox     
       */
      private JComboBox getJComboBox() {
           if (jComboBox == null) {
                String[] items = {"1", "2", "3", "4", "5"};
                jComboBox = new JComboBox(items);
                jComboBox.addActionListener(new java.awt.event.ActionListener() {
                     public void actionPerformed(java.awt.event.ActionEvent e) {
                          showDialog();
                     }
                });
           }
           return jComboBox;
      }

      protected void showDialog() {
           JOptionPane.showMessageDialog(this, "Selection made");
      }

 }

我使用的代码非常复杂,所以我在这里汇总了一个基本的代码示例。通过设置外观,只需单击2次即可点击有效选项,但如果没有它,则只需单击一下即可。 (在构造函数中注释掉setLookAndFeel() )。

有没有人有任何想法如何解决这个问题,以确保无论外观如何都只需要点击一次?

提前致谢

3 个答案:

答案 0 :(得分:1)

将代码包装在invokeLater中,让组合框在显示对话框之前自行重绘:

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        showDialog();
    }
});

答案 1 :(得分:0)

从内部类来看,要访问外部类中的变量,需要引用ComboBox.this.myBool。通常情况下,如果它是明确的,你可以做myBool。

public class ComboBox {

    private boolean myBool = false;

    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            boolean myBoolAgain = ComboBox.this.myBool;
            showDialog();
        }
    });
}

答案 2 :(得分:0)

在为JComboBox实现ItemListener时遇到了类似的问题,如果满足特定条件,它将在ItemEvent.DESELECTED事件之后向用户询问问题。由于ItemListener实现可能会根据用户的回答恢复选择,因此,将新的Runnable分配给EDT并不是一种选择-带有问题的JOptionPane需要显示在ItemListener中,这表明了所描述的问题OP。

即使创建并显示了后续的模态对话框,JComboBox的弹出窗口也会在显示时保持焦点,因此您需要使用JComboBox.hidePopup()在显示JOptionPane之前将其隐藏。这样做可以使所显示的对话框焦点集中在预期的位置,而无需双击。