0

I coded a Java Swing component that shows a button twice when it is clicked. However, I only want the button to appear once when clicked. My code is below. Does anyone know what I am missing?

import java.awt.event.*;



public class checkIt2 implements ItemListener { 

    public void itemStateChanged(ItemEvent e) { 


   if(e.getStateChange() == ItemEvent.SELECTED) { 



         javax.swing.JOptionPane.showMessageDialog(null, "Check box 2 is selected");
         JDBC_Demo6.check2.setSelected(true);


    } 

    if (e.getStateChange() == ItemEvent.DESELECTED) { 

        JDBC_Demo6.check1.setSelected(false);
    }




    }

}

Here is the code in the JDBC_Demo6 class that pertains to the JCheckBox ItemListener class:

    public class JDBC_Demo6 extends JFrame implements ActionListener {

    public static JTextArea textArea;
    static String critical_data; 
    private final static String newline = "\n";
    public static JCheckBox check1;
    public static JCheckBox check2;



public JDBC_Demo6(String s) {
    super(s);

}

public void addComponentsToPane(final Container pane) { 

    textArea = new JTextArea(20, 75);

   /* final JPanel compsToExperiment = new JPanel(new GridBagLayout()); */

    // GridBagConstraint for button 
    /* This puts the buttons in the very center of the GUI */




    //get Database data 
    JsonDB a = new JsonDB();

    //store the output from the getDB method in this ArrayList collection 
    ArrayList<String> tmp = a.getDB();

    //loop through the ArrayList and append each string to the text area
    JScrollPane scrollPane = new JScrollPane();
    //add a scrollpane to the GUI
    //scrollPane.setSize(new Dimension(100, 100));


    /* loop through the ArrayList with the results of the SQL query and then add them to the JPanel  */
    for(String s: tmp) {

        textArea.append("From the database -> " + s + "\n");
    }


    scrollPane.setViewportView(textArea);
    this.add(scrollPane);
    scrollPane.updateUI();

    /* add buttons */ 
    JButton jB = new JButton("Send To ESB");
    JButton jB2 = new JButton("Cancel");

    jB.addActionListener(new goButton());
    jB2.addActionListener(new cancelButton());
    this.add(jB);
    this.add(jB2);

    /* check boxes */ 
    check1 = new JCheckBox("Check Box 1");
    check2 = new JCheckBox("Check Box 2");

    check1.addItemListener(new checkIt());
    check2.addItemListener(new checkIt2());

    this.add(check1);
    this.add(check2);



}



/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event dispatch thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JDBC_Demo6 frame = new JDBC_Demo6("JDBC Example #6");
    frame.setSize(50, 50);
    frame.setLayout(new FlowLayout());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Add contents to the window.
    frame.addComponentsToPane(frame.getContentPane());

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event dispatch thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

public void actionPerformed(ActionEvent ae) { 

}

} // end class 
user3808269
  • 1,321
  • 3
  • 21
  • 40
  • 1
    Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Dec 26 '14 at 21:27
  • The only other important information, I can think of, is that the check1 and check 2 references are static and reference a JCheckBox. JDBC_Demo6 is the class that these static object references are in. :) – user3808269 Dec 26 '14 at 22:27
  • My test code works just fine, it's something you are doing in you code which you aren't showing us. Either provide a self-contained, compilable and runnable example or the question will be closes... – MadProgrammer Dec 26 '14 at 23:07
  • @MadProgrammer `checkIt` is the class for the ItemListener as shown above. There are two classes one for each button to control what happens when the button is clicked. – user3808269 Dec 26 '14 at 23:30
  • @MadProgrammer I added the entire java source code above. – user3808269 Dec 26 '14 at 23:34
  • 1- There is NO reason why `textArea`, `check1` or `check2` should be `static`, `static` is NOT a cross class communication mechanism. If you need to access values from a class then provide appropriate assessors and pass a reference of the class to who ever needs it. Try and avoid exposing components to other classes, as this invites modifications which you may not want. 2- You're still missing `checkIt`, but otherwise, the code works fine. Take a read through [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) and understand what it's asking for – MadProgrammer Dec 26 '14 at 23:52

2 Answers2

0

Use either check1 or check2.

import java.awt.event.*;

public class checkIt2 implements ItemListener { 

    public void itemStateChanged(ItemEvent e) { 

        if(e.getStateChange() == ItemEvent.SELECTED) { 

            javax.swing.JOptionPane.showMessageDialog(null, "Check box 2 is selected");
            JDBC_Demo6.check1.setSelected(true);

        } 

        if (e.getStateChange() == ItemEvent.DESELECTED) { 

            JDBC_Demo6.check1.setSelected(false);
        }

    }

}
Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
Dalton Phan
  • 1
  • 1
  • 5
  • Thanks for helping to debug this. :D I tried this, after correcting my error you found, but still get the two pop-up boxes for one click. :/ – user3808269 Dec 26 '14 at 22:26
0

It is happening twice because the call JDBC_Demo6.check1.setSelected(true); triggers another call to ItemListener.itemStateChanged(). In this case it would be easier to use an ActionLister or a ChangeLister instead of an ItemListener, like in the code that follows. Although the call JDBC_Demo6.check1.setSelected(true); wont trigger another ActionListener.actionPerformed(), like it does for ItemListeners, the call is redundant and you should remove it.
Test this ActionListener to see if it works for you:

    public class checkIt2 implements ActionListener { 

        @Override
        public void actionPerformed(ActionEvent e) {
            javax.swing.JOptionPane.showMessageDialog(null, "selected: " +
                    ((JCheckBox)e.getSource()).isSelected());
        }

    }

And use this to register the listener:

    check2.addActionListener(new checkIt2());
ulix
  • 999
  • 9
  • 13
  • Well that's odd @MadProgrammer. In my test I've got the same issues that were reported in the question (the dialog showing up twice). This urges me to make a few more tests. I'll let you know. – ulix Dec 27 '14 at 16:35
  • @MadProgrammer, I've ran a few more tests here and the reported issues always happens if the line `JDBC_Demo6.check2.setSelected(true);` is present AND as long as `JDBC_Demo6.check2` refers to the source of the event. Could you please replace that line by `((JCheckBox)e.getSource()).setSelected(true);` in your test code just to make sure the method being called is the actual source of the event? I still think the main issue here is the use of ItemListener. – ulix Dec 28 '14 at 05:18
  • Copy and pasted the code presented by the OP (and after correcting for the missing code) and can not replicate the issue, I only have a SINGLE event triggered. It is impossible to trigger a double event becase the `JToggleButton#setSelected` method checks to see if the state been set is the same as the current state or not `if (isSelected() == b) {`. My "guess" is, there is something in `checkIt` that we are not seeing... – MadProgrammer Dec 28 '14 at 05:32