2011-11-26 39 views
5

有人可以向我解释为什么当我将JOptionPane放入ItemListener时为什么我丢失了选择(由setSelected()设置)为JCheckBox? 这是一个错误?为什么setSelected on JCheckBox失去效果?

很奇怪,如果这个过程延迟invokeLater()setSelected()正如我所料。

enter image description hereenter image description here

从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+ question。我已经看到过这个,并且已经解决了它 - 通过排队在EDT上显示JOptionPane,但是我无法解释它,因为我没有时间或精力来揣测源代码。 –

+0

@Hovercraft Full Of Eels我在这里发布这个问题之前调试了Java API方法,一切都看起来像是正确的,在这两种情况下通知器都是在这个方法内部完成的,但我仍然找不到差异(Java方法内的步骤)纯JCheckBox和JCheckBox与JOptionPane,感谢您的确认 – mKorbel

回答

4

这是Oracle Bug ID:6924233确认的已知错误JOptionPane显然会导致使用复选框value = false生成另一个事件。

建议的修复方法是使用invokeLater实例化JOptionPane

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

在Mac OS X & Ubuntu的我看不出有任何区别:从DESELECTED状态开始,我点击复选框。我看到复选标记立即出现,然后是选项窗格。无论是否有Runnable,我都可以得到相同的结果。

在Windows上,结果如上所述,但当选项窗格显示在前景中时,我看到了一个微小的复选标记闪烁。效果在仿真器中更容易看到,例如VirtualBox,这可能会降低速度。排队Runnable可恢复正常操作。

+0

对不起,这不是一个真正的答案,但它可能指导一个错误的搜索。 – trashgod

+0

(每次)我赞赏在MAC/Linux上运行任何代码,或者要求与这些Native OS兼容的代码+1 – mKorbel

相关问题