自定义JComboBox:当LAF是系统LAF时,“无限循环事件”

时间:2013-01-20 14:01:37

标签: java swing jcombobox look-and-feel

我自定义我的JComboBox如下。 程序在默认的LAF下运行正常,但每当我将LAF更改为System LAF(另一个LAF,Nimbus,没问题)时,单击按钮后会出现无限循环。我看到actionPerformed方法被无限调用 请帮我解决这个问题。我用jdk 1.6.0_33
如果有任何不明确的意思,我很抱歉。我的英语不好 提前谢谢。

package sig.dw.ui;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
//import javax.swing.event.EventListenerList;

/**
*
* @author congnh
*/
public class ButtonableComboBox extends JComboBox{

    private ButtonableComboBoxEditor comboBoxEditor;
    public ButtonableComboBox(){
        super();
        comboBoxEditor = new ButtonableComboBoxEditor();
        // eventListenerList = new EventListenerList();
        setEditable(true);
        setEditor(comboBoxEditor);
    }


    public ButtonableComboBox(Object[] items){
        this();
        setModel(new DefaultComboBoxModel(items));
    }


    public void addButtonListener(ActionListener listener){
        comboBoxEditor.addActionListener(listener);
    }


    public void removeButtonListener(ActionListener listener){
        comboBoxEditor.removeActionListener(listener);
    }


    class ButtonableComboBoxEditor implements ComboBoxEditor{
        private JButton button;
        public ButtonableComboBoxEditor(){
            button = new JButton();
        }
        @Override
        public Component getEditorComponent() {
            return button;
        }
        @Override
        public void setItem(Object anObject) {
            if(anObject!=null){
                button.setText(anObject.toString());
            }
        }
        @Override
        public Object getItem() {
            return button.getText();
        }

        @Override
        public void selectAll() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void addActionListener(ActionListener l) {
            System.out.println("add new listener");
            button.addActionListener(l);
        }

        @Override
        public void removeActionListener(ActionListener l) {
            button.removeActionListener(l);
        }
    }

    public static void main(String args[]){
        javax.swing.SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                String[] comboBoxItems = {"Browse","Explorer","Firefox","IE","Chrome","Opera"};
                JFrame frame = new JFrame();
                JPanel panel = new JPanel();
                panel.setLayout(new FlowLayout());
                ButtonableComboBox bcb = new ButtonableComboBox(comboBoxItems);
                bcb.addButtonListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println(e.getActionCommand());
                    }
                });
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                panel.add(bcb);
                frame.add(panel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

1 个答案:

答案 0 :(得分:3)

作为参考,我在Mac OS X / Java 1.6.0_37上看到了StackOverflowError MotifLookAndFeel,但MetalLookAndFeelNimbusLookAndFeelAquaLookAndFeel没有看到doClick()。使用下面的示例和看到here的L& F选择器,我得到了下面的堆栈跟踪,因为UI委托以递归方式调用StackOverflowError。我没有看到明显的解决方法。

附录:我在Ubuntu 12 / Java 1.6.0_24上看到MotifLookAndFeel的类似MetalLookAndFeel,但不是NimbusLookAndFeelGTKLookAndFeelimport java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.ComboBoxEditor; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class ButtonableComboBox extends JComboBox { private ButtonableComboBoxEditor comboBoxEditor; public ButtonableComboBox() { comboBoxEditor = new ButtonableComboBoxEditor(); setEditor(comboBoxEditor); setEditable(true); } public ButtonableComboBox(Object[] items) { this(); setModel(new DefaultComboBoxModel(items)); } public void addButtonListener(ActionListener listener) { comboBoxEditor.addActionListener(listener); } public void removeButtonListener(ActionListener listener) { comboBoxEditor.removeActionListener(listener); } class ButtonableComboBoxEditor implements ComboBoxEditor { private JButton button = new JButton(); @Override public Component getEditorComponent() { return button; } @Override public void setItem(Object anObject) { if (anObject != null) { button.setText(anObject.toString()); } } @Override public Object getItem() { return button.getText(); } @Override public void selectAll() { System.out.println("select all"); button.requestFocus(); } @Override public void addActionListener(ActionListener l) { System.out.println("add listener"); button.addActionListener(l); } @Override public void removeActionListener(ActionListener l) { System.out.println("remove listener"); button.removeActionListener(l); } } public static void main(String args[]) { javax.swing.SwingUtilities.invokeLater(new Runnable() { @Override public void run() { String[] comboBoxItems = { "Browse", "Explorer", "Firefox", "IE", "Chrome", "Opera"}; JFrame frame = new JFrame(); JPanel panel = new JPanel(); ButtonableComboBox bcb = new ButtonableComboBox(comboBoxItems); bcb.addButtonListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println(e.getActionCommand()); } }); panel.add(bcb); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // https://stackoverflow.com/a/11949899/230513 frame.add(createToolBar(frame), BorderLayout.NORTH); frame.add(panel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } }

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
  at sun.font.FontManager.getFont2D(Native Method)
  at sun.java2d.SunGraphics2D.checkFontInfo(SunGraphics2D.java:780)
  at sun.java2d.SunGraphics2D.getFontInfo(SunGraphics2D.java:941)
  at sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:32)
  at sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:3054)
  at sun.swing.SwingUtilities2.drawString(SwingUtilities2.java:517)
  at sun.swing.SwingUtilities2.drawStringUnderlineCharAt(SwingUtilities2.java:538)
  at javax.swing.plaf.basic.BasicButtonUI.paintText(BasicButtonUI.java:294)
  at javax.swing.plaf.basic.BasicButtonUI.paintText(BasicButtonUI.java:319)
  at javax.swing.plaf.basic.BasicButtonUI.paint(BasicButtonUI.java:207)
  at com.sun.java.swing.plaf.motif.MotifButtonUI.paint(MotifButtonUI.java:91)
  at javax.swing.plaf.ComponentUI.update(ComponentUI.java:153)
  at javax.swing.JComponent.paintComponent(JComponent.java:760)
  at javax.swing.JComponent.paint(JComponent.java:1037)
  at javax.swing.JComponent.paintChildren(JComponent.java:870)
  at javax.swing.JComponent.paint(JComponent.java:1046)
  at javax.swing.JComponent.paintChildren(JComponent.java:870)
  at javax.swing.JComponent.paint(JComponent.java:1046)
  at javax.swing.JComponent._paintImmediately(JComponent.java:5106)
  at javax.swing.JComponent.paintImmediately(JComponent.java:4890)
  at javax.swing.JComponent.paintImmediately(JComponent.java:4902)
  at javax.swing.AbstractButton.doClick(AbstractButton.java:352)
  at javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed(BasicRootPaneUI.java:191)
  at javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed(BasicComboBoxUI.java:1575)
  at javax.swing.plaf.basic.BasicComboBoxUI$Handler.actionPerformed(BasicComboBoxUI.java:1904)
  at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
  at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
  at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
  at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
  at javax.swing.AbstractButton.doClick(AbstractButton.java:389)
  ...
  at javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed(BasicRootPaneUI.java:191)
  at javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed(BasicComboBoxUI.java:1575)
  at javax.swing.plaf.basic.BasicComboBoxUI$Handler.actionPerformed(BasicComboBoxUI.java:1904)
  at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
  at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
  at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
  at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
  at javax.swing.AbstractButton.doClick(AbstractButton.java:389)
  at javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed(BasicRootPaneUI.java:191)
  at javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed(BasicComboBoxUI.java:1575)

SSCCE:

{{1}}