我自定义我的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);
}
});
}
}
答案 0 :(得分:3)
作为参考,我在Mac OS X / Java 1.6.0_37上看到了StackOverflowError
MotifLookAndFeel
,但MetalLookAndFeel
,NimbusLookAndFeel
或AquaLookAndFeel
没有看到doClick()
。使用下面的示例和看到here的L& F选择器,我得到了下面的堆栈跟踪,因为UI委托以递归方式调用StackOverflowError
。我没有看到明显的解决方法。
附录:我在Ubuntu 12 / Java 1.6.0_24上看到MotifLookAndFeel
的类似MetalLookAndFeel
,但不是NimbusLookAndFeel
,GTKLookAndFeel
或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);
}
});
}
}
。
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}}