2011-11-26 14 views
5

Czy ktoś może mi wyjaśnić, dlaczego utraciłem wybór (ustawiony przez setSelected()) dla JCheckBox, kiedy wstawiam JOptionPane do ItemListener? Czy to błąd?Dlaczego funkcja setSelected w JCheckBox traci moc?

To ciekawe, że jeśli ten proces zostanie opóźniony o invokeLater(), setSelected() działa poprawnie zgodnie z oczekiwaniami.

enter image description hereenter image description here

z 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(); 
      } 
     }); 
    } 
} 
+1

1+ pytanie. Widziałem to już wcześniej i rozwiązałem go tak jak ty - kolejkując wyświetlanie JOptionPane na EDT, ale nie mogę tego wyjaśnić, ponieważ nie miałem czasu ani energii, aby przepchnąć kod źródłowy. –

+0

@Hovercraft Pełne węgorzy Debuguję to wewnątrz metod API Java, zanim zamieszczę tutaj to pytanie, wszystko wygląda jak poprawnie, notifier jest wykonywany wewnątrz tej metody w obu przypadkach, nadal nie mogę znaleźć różnicy między krokami (kroki wewnątrz metody Java) zwykłe JCheckBox i JCheckBox z JOptionPane, dziękuję za twoje potwierdzenie – mKorbel

Odpowiedz

4

Jest to znany błąd potwierdzony przez Oracle Bug ID:6924233 Najprawdopodobniej numer JOptionPane powoduje wygenerowanie kolejnego zdarzenia z wartością pola wyboru = false.

Zalecaną poprawką jest utworzenie instancji JOptionPane przy użyciu 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) 
2

na Mac OS X & Ubuntu nie widzę żadnej różnicy: od stanu DESELECTED, klikam na pola wyboru. Widzę, że znak wyboru pojawia się natychmiast, a następnie panel opcji. Otrzymuję ten sam wynik z lub bez Runnable.

W systemie Windows wynik jest taki, jak opisano, ale widzę małe migotanie znacznika, gdy okienko opcji pojawia się na pierwszym planie. Efekt jest łatwiejszy do zauważenia w emulatorze, takim jak VirtualBox, co może spowolnić działanie. Kolejkowanie Runnable przywraca normalną pracę.

+0

Niestety, to nie jest odpowiedź, ale może to prowadzić do szukania błędu. – trashgod

+0

(za każdym razem) Doceniam runnig dowolny kod na MAC/Linux, lub prosząc o kod zgodny z tymi Native OS +1 – mKorbel