1

I am having a problem with a JComboBox and a JOptionPane dialog. The situation is this:

  • It needs to run from a Dialog, not a Frame
  • Before data is set no check needs to be done
  • After data is set changes need to be validated

I have a JComboBox with initial data in it and I have an ActionListener which, on selection, displays a JOptionPane dialog with a warning about revalidating.

When a selection is made the dialog appears as normal but the JComboBox doesn't finish it's cycle and keeps the JComboBox open until the dialog is clicked and then you need to do a further click to choose an option (regardless whether the first click is on top of the button).

 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");
      }

 }

The code I am using is quite complex so I have thrown together a basic example of code here. With the look and feel set it required 2 clicks to click on a valid option but without it it required a single click. (Comment out setLookAndFeel() in the constructor).

Does anyone have any ideas how to fix this to make sure it only requires 1 click regardless of the look and feel?

Thanks in advance

4

3 回答 3

1

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

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        showDialog();
    }
});
于 2013-07-03T15:35:54.213 回答
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();
        }
    });
}
于 2016-01-03T12:28:21.503 回答
0

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

即使创建并显示了后续的模态对话框,JComboBox 的弹出窗口也会在显示时保持焦点,因此您需要在显示 JOptionPane 之前隐藏它,使用JComboBox.hidePopup(). 这样做会在按预期显示时提供生成的对话框焦点,并且不需要双击。

于 2020-05-07T09:41:49.263 回答