Why does setSelected on JCheckBox lose effect?
Asked Answered
N

2

5

Can someone explain to me why I lost the selection (set by setSelected()) for JCheckBox when I put the JOptionPane into the ItemListener? Is this a bug ?

It is curious, that if this process is delayed with invokeLater(), setSelected() works correctly as I expected.

enter image description here enter image description here

from SSCCE

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ComponentEventDemo extends JPanel
        implements ComponentListener, ItemListener {

    private static final long serialVersionUID = 1L;
    private JFrame frame;
    private JTextArea display;
    private String newline = "\n";
    private JTextField field1;

    public ComponentEventDemo() {
        super(new BorderLayout());
        display = new JTextArea(10, 25);
        display.setEditable(false);
        JPanel panel = new JPanel(new GridLayout(0, 2));
        field1 = new JTextField();
        field1.setDisabledTextColor(Color.red);
        JCheckBox checkbox = new JCheckBox("Label visible", true);
        checkbox.addItemListener(this);
        panel.add(checkbox);
        panel.add(field1);
        panel.addComponentListener(this);
        JScrollPane scrollPane = new JScrollPane(display);
        frame = new JFrame("ComponentEventDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(panel, BorderLayout.SOUTH);
        frame.addComponentListener(this);
        frame.setLocation(200, 200);
        frame.pack();
        frame.setVisible(true);
    }

    public void itemStateChanged(ItemEvent evt) {
        System.out.println("STATE CHANGED!");
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            //javax.swing.SwingUtilities.invokeLater(new Runnable() {

            //public void run() {
            int returnVal = JOptionPane.showConfirmDialog(display,
                    "Bla Bla Bla Text");
            if (returnVal == JOptionPane.OK_OPTION) {
                field1.setText("SELECTED - OK btn");
            } else if (returnVal == JOptionPane.NO_OPTION) {
                field1.setText("SELECTED - NO btn");
            } else if (returnVal == JOptionPane.CANCEL_OPTION) {
                field1.setText("SELECTED - Cancel btn");
            } else if (returnVal == JOptionPane.CLOSED_OPTION) {
                field1.setText("SELECTED - Close btn");
            }
            //}
            //});
        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            field1.setText("DESELECTED");
        }
    }

    protected void displayMessage(String message) {
        display.append(message + newline);
        display.setCaretPosition(display.getDocument().getLength());
    }

    public void componentHidden(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " ---> Hidden");
    }

    public void componentMoved(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " ---> Moved");
    }

    public void componentResized(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " ---> Resized ");
    }

    public void componentShown(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " ---> Shown");

    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                ComponentEventDemo ced = new ComponentEventDemo();
            }
        });
    }
}
Newsy answered 26/11, 2011 at 23:41 Comment(2)
1+ question. I've seen this before and have solved it as you have -- by queuing the display of the JOptionPane on the EDT, but I can't explain it as I've not had time or energy to slog through the source code yet.Alsworth
@Hovercraft Full Of Eels I debug that inside Java API methods, before I posting this question here, everything looks like correctly, notifier is done inside this method in both cases, still I can't found difference betweens (steps inside Java method) plain JCheckBox and JCheckBox with JOptionPane, thanks for your comfirmationNewsy
H
4

It is a known bug as acknowledged by Oracle Bug ID:6924233 The JOptionPane apparently causes another event to be generated with a check box value = false.

The recommended fix is to instantiate the JOptionPane using invokeLater.

Submitted On 09-MAR-2010

The change is in the BasicButtonListener -  Method focusLost()

In 1.6.0_18 it is

       ...
       ButtonModel model = b.getModel();
       model.setPressed(false);
       model.setArmed(false);

in 1.6.0_10 it was

       ...
       ButtonModel model = b.getModel();
       model.setArmed(false);
       model.setPressed(false);

(The order of the statements changed)

And a setPressed(false) with armed==true leads on an ToggleButton like 
the JCheckBox to a change of the selection (see ToggleButtonModel) 
Hydric answered 28/11, 2011 at 6:46 Comment(0)
K
2

On Mac OS X & Ubuntu I don't see any difference: Starting from the DESELECTED state, I click on the checkbox. I see the check mark appear immediately, followed by the option pane. I get the same result with or without the Runnable.

On Windows, the result is as described, but I see a tiny flicker of the check mark as the option pane comes to the foreground. The effect is easier to see in an emulator, such as VirtualBox, which can slow things down. Queueing the Runnable restores normal operation.

Kickstand answered 27/11, 2011 at 1:17 Comment(2)
Sorry, this isn't really an answer, but it might guide teh search for a bug.Kickstand
(every time) I appreciating runnig any code on the MAC/Linux, or asking for code compatible with these Native OS +1Newsy

© 2022 - 2024 — McMap. All rights reserved.