如何更改JComboBox下拉列表的宽度?

时间:2009-06-05 14:00:01

标签: java swing combobox

我有一个可编辑的JComboBox,其中包含单个字母值的列表。因此,组合框非常小。

每个字母都有特殊含义,对于很少使用的字母,有时用户不清楚。因此,我创建了一个自定义ListCellRenderer,它显示了下拉列表中每个字母的含义。

不幸的是,这个解释不适合下拉列表,因为它与小的一样,因为它与组合框的宽度相同。

有没有办法让下拉列表比组合框更宽?

这就是我想要实现的目标:

 ---------------------
| Small JCombobox | V |
 --------------------------------------------
| "Long item 1"                              |
 --------------------------------------------
| "Long item 2"                              |
 --------------------------------------------
| "Long item 3"                              |
 --------------------------------------------

我无法改变组合框的宽度,因为该应用程序是旧的遗留应用程序的重新创建,其中某些东西必须与之前完全一样。 (在这种情况下,组合框必须不惜一切代价保持它的小尺寸)

7 个答案:

答案 0 :(得分:16)

答案 1 :(得分:14)

我认为使用公共API执行此操作的唯一方法是编写自定义UI(two bugs处理此问题。)

如果你只是想要快速和肮脏的东西,我发现这种方式使用实现细节来做(here):

public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
    JComboBox box = (JComboBox) e.getSource();
    Object comp = box.getUI().getAccessibleChild(box, 0);
    if (!(comp instanceof JPopupMenu)) return;
    JComponent scrollPane = (JComponent) ((JPopupMenu) comp).getComponent(0);
    Dimension size = new Dimension();
    size.width = box.getPreferredSize().width;
    size.height = scrollPane.getPreferredSize().height;
    scrollPane.setPreferredSize(size);
    //  following line for Tiger
    // scrollPane.setMaximumSize(size);
}

将其放在PopupMenuListener中,可能适合您。

或者您可以使用first linked bug

中的代码
class StyledComboBoxUI extends BasicComboBoxUI {
  protected ComboPopup createPopup() {
    BasicComboPopup popup = new BasicComboPopup(comboBox) {
      @Override
      protected Rectangle computePopupBounds(int px,int py,int pw,int ph) {
        return super.computePopupBounds(
            px,py,Math.max(comboBox.getPreferredSize().width,pw),ph
        );
      }
    };
    popup.getAccessibleContext().setAccessibleParent(comboBox);
    return popup;
  }
}

class StyledComboBox extends JComboBox {
  public StyledComboBox() {
    setUI(new StyledComboBoxUI());
  }
}

答案 2 :(得分:14)

这是Santhosh Kumar的一个很好的解决方案,不需要弄乱UI和其他令人讨厌的东西!

http://www.jroller.com/santhosh/entry/make_jcombobox_popup_wide_enough

import javax.swing.*; 
import java.awt.*; 
import java.util.Vector; 

// got this workaround from the following bug: 
//      http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4618607 
public class WideComboBox extends JComboBox{ 

    public WideComboBox() { 
    } 

    public WideComboBox(final Object items[]){ 
        super(items); 
    } 

    public WideComboBox(Vector items) { 
        super(items); 
    } 

        public WideComboBox(ComboBoxModel aModel) { 
        super(aModel); 
    } 

    private boolean layingOut = false; 

    public void doLayout(){ 
        try{ 
            layingOut = true; 
                super.doLayout(); 
        }finally{ 
            layingOut = false; 
        } 
    } 

    public Dimension getSize(){ 
        Dimension dim = super.getSize(); 
        if(!layingOut) 
            dim.width = Math.max(dim.width, getPreferredSize().width); 
        return dim; 
    } 
}

答案 3 :(得分:5)

这是tutiez的一个很好的解决方案。

在设置弹出列表的维度之前,它会从中获取最大的项目并计算完全显示它所需的宽度。

public class WiderDropDownCombo extends JComboBox {

    private String type;
    private boolean layingOut = false;
    private int widestLengh = 0;
    private boolean wide = false;

    public WiderDropDownCombo(Object[] objs) {
        super(objs);
    }

    public boolean isWide() {
        return wide;
    }

    // Setting the JComboBox wide
    public void setWide(boolean wide) {
        this.wide = wide;
        widestLengh = getWidestItemWidth();

    }

    public Dimension getSize() {
        Dimension dim = super.getSize();
        if (!layingOut && isWide())
            dim.width = Math.max(widestLengh, dim.width);
        return dim;
    }

    public int getWidestItemWidth() {

        int numOfItems = this.getItemCount();
        Font font = this.getFont();
        FontMetrics metrics = this.getFontMetrics(font);
        int widest = 0;
        for (int i = 0; i < numOfItems; i++) {
            Object item = this.getItemAt(i);
            int lineWidth = metrics.stringWidth(item.toString());
            widest = Math.max(widest, lineWidth);
        }

        return widest + 5;
    }

    public void doLayout() {
        try {
            layingOut = true;
            super.doLayout();
        } finally {
            layingOut = false;
        }
    }

    public String getType() {
        return type;
    }

    public void setType(String t) {
        type = t;
    }

    public static void main(String[] args) {
        String title = "Combo Test";
        JFrame frame = new JFrame(title);

        String[] items = {
                "I need lot of width to be visible , oh am I visible now",
                "I need lot of width to be visible , oh am I visible now" };
        WiderDropDownCombo simpleCombo = new WiderDropDownCombo(items);
        simpleCombo.setPreferredSize(new Dimension(180, 20));
        simpleCombo.setWide(true);
        JLabel label = new JLabel("Wider Drop Down Demo");

        frame.getContentPane().add(simpleCombo, BorderLayout.NORTH);
        frame.getContentPane().add(label, BorderLayout.SOUTH);
        int width = 200;
        int height = 150;
        frame.setSize(width, height);
        frame.setVisible(true);

    }
}

上面的代码已经成为快速测试的主要内容。但请注意,如果您想要进行垂直滚动,可以将下面的语句调整为 20

return widest + 5;

希望它对将来参考有用!

答案 4 :(得分:1)

听起来你需要自己编写ComboBoxUI

有一个很好的例子here,展示了如何实现这一目标。

另请注意,您可能感兴趣的方法是createPopup()方法。这是为组合框创建弹出窗口的方法,您可以在其中自定义它。

答案 5 :(得分:0)

您可能希望使用setSize()方法。

combo.setSize(200, combo.getPreferredSize().height);

答案 6 :(得分:0)

这里有一段简单的代码,没有扩展JComboBox,也没有任何类

在此示例中,下拉列表始终为500。 您也可以修改高度或位置。

        FaceCorrectiveReasonComboBox.getTextComponent().setUI(new BasicComboBoxUI() {
            @Override protected ComboPopup createPopup() {
                return new BasicComboPopup(comboBox) {
                    protected Rectangle computePopupBounds(int px,int py,int pw,int ph) {
                        return super.computePopupBounds(px, py, 500, ph);
                    }                       
                };
            }
        });