2009-06-05 52 views
26

我有一个可编辑的JComboBox其中包含单个字母值的列表。因为这个组合框非常小。如何更改JComboBox下拉列表的宽度?

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

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

有什么办法让下拉列表比组合框宽吗?

这就是我想要达到的目标:

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

,因为应用程序是一个旧的遗留应用程序,其中有些事情必须要准确,因为他们之前的娱乐我不能改变组合框的宽度。 (在这种情况下,组合框必须不惜一切代价保持小尺寸)

回答

14

我相信使用公共API做到这一点的唯一方法是编写一个自定义UI(有twobugs处理这个)。

如果你只是想要快速和肮脏的,我发现这种方式使用的实施细节做(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()); 
    } 
} 
+0

这两种方法似乎都可行,但popupMenuWillBecomeVisible只有在您还提供自定义ListCellRenderer时才有效。默认的一个似乎以原始大小切割字符串。 – 2009-06-05 14:29:39

+0

当JComboBox(OSX)中有8个项目出现时,第一个不适用于我。而第二个在MAC上也有窗口的外观...... – Grains 2014-01-10 14:50:25

1

听起来像你需要编写自己的ComboBoxUI

有一个很好的例子here,显示了如何完成此操作。

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

13

下面是Santhosh库马尔很好的解决方案,而不需要混乱与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

这里是一个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); 

    } 
} 

上面的代码已经是快速测试的主要代码。但请注意,如果您想要进行垂直滚动,以下声明可能会调整为大约

return widest + 5; 

希望它对未来的参考是有用的!

0

您可能想要使用setSize()方法。

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