2009-06-05 55 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);