2 Replies Latest reply: Oct 7, 2004 1:52 AM by 807587 RSS

    Make JComboBox only respond to user events

    807587
      I find it annoying that JComboBox attached to either ActionListener or ItemListener responds to non-user events, such as adding the first item, removing the last item, and calling setSelected(). In my form-based application, I often need to fill up the form with values. But whenever I'm loading up a combo box, its event listener gets inadvertently triggered, causing unexpected side affect.

      It seems JComboBox is the only Swing component that responds to non-user initiated actions. I'm having no problem setting the values JTextField, JCheckBox, etc. without it triggering an event.

      Therefore, I like to know if there's a way to make JComboBox NOT respond to non-user events.
        • 1. Re: Make JComboBox only respond to user events
          807587
          import java.awt.*;
          import java.awt.event.*;
          import javax.swing.*;
          import javax.swing.event.*;
          public class Test3 extends JFrame {
            JTextField jtf = new JTextField("Hello");
            JCheckBox jcb = new JCheckBox("Check");
            JCheckBox showEvents = new JCheckBox("Show Internal Events");
            JCheckBox runThread = new JCheckBox("Run Thread");
            boolean internalEvent=false;
            public Test3() {
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Container content = getContentPane();
                JPanel jp1 = new JPanel(), jp2 = new JPanel();
                content.add(jp1, BorderLayout.NORTH);
                jp1.add(jtf);
                jtf.addCaretListener(new CaretListener() {
                  public void caretUpdate(CaretEvent ce) {
                    if (!internalEvent || showEvents.isSelected()) {
                      System.out.println("JTF Caret Event(" + ce.getDot() + ")");
                    }
                  }
                });
                jp1.add(jcb);
                jcb.addChangeListener(new ChangeListener() {
                  public void stateChanged(ChangeEvent ae) {
                    if (!internalEvent || showEvents.isSelected()) {
                      System.out.println("JCB=" + jcb.isSelected());
                    }
                  }
                });
                content.add(jp2, BorderLayout.SOUTH);
                jp2.add(showEvents);
                jp2.add(runThread);
                new Thread(new Runnable() {
                  public void run() {
                    while(true) {
                      if (runThread.isSelected()) {
                        SwingUtilities.invokeLater(new Runnable() {
                          public void run() {
                            internalEvent = true;
                            jtf.setText("Hello");
                            jtf.requestFocus();
                            jcb.setSelected(!jcb.isSelected());
                            internalEvent = false;
                          }
                        });
                      }
                      try { Thread.sleep(2000); } catch (Exception e) {}
                    }
                  }
                }).start();
                setSize(300,300);
                setVisible(true);
            }
            public static void main(String[] args) { new Test3(); }
          }
          • 2. Re: Make JComboBox only respond to user events
            807587
            I've used that method before, but decided against it because of the spaghetti-ness introduced by using global flag. Namely, I find myself being uncertain about the state of a flag at any given section of the code.

            But seeing it used by other people (i.e. you) makes me reconsider this idea. I guess I just have ensure that the code between disableEvent() and enableEvent() contain only statements that sets component state, this would allow me to assume that event is enabled upon entry to any method in my system, except the event handler.

            Eric