2

JComboBox を次のようにカスタマイズします。プログラムはデフォルトの LAF で問題なく動作しましたが、LAF をシステム 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);
            }
        });
    }
}
4

1 に答える 1

3

参考までに、Mac OS X / Java 1.6.0_37 ではStackOverflowErrorforが表示されますが、 、、またはは表示されません。以下の例と、ここに示されている L&F セレクターを使用すると、UI デリゲートが再帰的に呼び出すと、次のスタック トレースが得られます。明らかな回避策は見当たりません。MotifLookAndFeelMetalLookAndFeelNimbusLookAndFeelAquaLookAndFeeldoClick()

補遺: Ubuntu 12 / Java 1.6.0_24 でも同様StackOverflowErrorの forが表示されますが、 、、またはは表示されません。MotifLookAndFeelMetalLookAndFeelNimbusLookAndFeelGTKLookAndFeel

スレッド「AWT-EventQueue-0」での例外 java.lang.StackOverflowError
  sun.font.FontManager.getFont2D(ネイティブメソッド)
  sun.java2d.SunGraphics2D.checkFontInfo(SunGraphics2D.java:780) で
  sun.java2d.SunGraphics2D.getFontInfo(SunGraphics2D.java:941) で
  sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:32) で
  sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:3054) で
  sun.swing.SwingUtilities2.drawString(SwingUtilities2.java:517) で
  sun.swing.SwingUtilities2.drawStringUnderlineCharAt(SwingUtilities2.java:538) で
  javax.swing.plaf.basic.BasicButtonUI.paintText(BasicButtonUI.java:294)で
  javax.swing.plaf.basic.BasicButtonUI.paintText(BasicButtonUI.java:319)で
  javax.swing.plaf.basic.BasicButtonUI.paint(BasicButtonUI.java:207)で
  com.sun.java.swing.plaf.motif.MotifButtonUI.paint(MotifButtonUI.java:91) で
  javax.swing.plaf.ComponentUI.update(ComponentUI.java:153) で
  javax.swing.JComponent.paintComponent(JComponent.java:760) で
  javax.swing.JComponent.paint(JComponent.java:1037)
  javax.swing.JComponent.paintChildren(JComponent.java:870)で
  javax.swing.JComponent.paint(JComponent.java:1046)
  javax.swing.JComponent.paintChildren(JComponent.java:870)で
  javax.swing.JComponent.paint(JComponent.java:1046)
  javax.swing.JComponent._paintImmediately(JComponent.java:5106)で
  javax.swing.JComponent.paintImmediately(JComponent.java:4890)で
  javax.swing.JComponent.paintImmediately(JComponent.java:4902)で
  javax.swing.AbstractButton.doClick(AbstractButton.java:352) で
  javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed (BasicRootPaneUI.java:191) で
  javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed (BasicComboBoxUI.java:1575) で
  javax.swing.plaf.basic.BasicComboBoxUI$Handler.actionPerformed (BasicComboBoxUI.java:1904) で
  javax.swing.AbstractButton.fireActionPerformed (AbstractButton.java:2028) で
  javax.swing.AbstractButton$Handler.actionPerformed (AbstractButton.java:2351) で
  javax.swing.DefaultButtonModel.fireActionPerformed (DefaultButtonModel.java:387) で
  javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) で
  javax.swing.AbstractButton.doClick(AbstractButton.java:389)で
  ...
  javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed (BasicRootPaneUI.java:191) で
  javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed (BasicComboBoxUI.java:1575) で
  javax.swing.plaf.basic.BasicComboBoxUI$Handler.actionPerformed (BasicComboBoxUI.java:1904) で
  javax.swing.AbstractButton.fireActionPerformed (AbstractButton.java:2028) で
  javax.swing.AbstractButton$Handler.actionPerformed (AbstractButton.java:2351) で
  javax.swing.DefaultButtonModel.fireActionPerformed (DefaultButtonModel.java:387) で
  javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) で
  javax.swing.AbstractButton.doClick(AbstractButton.java:389)で
  javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed (BasicRootPaneUI.java:191) で
  javax.swing.plaf.basic.BasicComboBoxUI$Actions.actionPerformed (BasicComboBoxUI.java:1575) で

SSCCE:

import 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);
            }
        });
    }
}
于 2013-01-20T16:54:42.593 に答える