Подтвердить что ты не робот

Как изменить ширину раскрывающегося списка JComboBox?

У меня есть редактируемый JComboBox, который содержит список однобуквенных значений. Из-за этого combobox очень мал.

Каждая буква имеет особое значение, которое иногда не понятно пользователю в случае редко используемых писем. Из-за этого я создал пользовательский ListCellRenderer, который показывает значение каждой буквы в раскрывающемся списке.

К сожалению, это объяснение не вписывается в выпадающее меню, потому что оно мало, потому что оно имеет ту же ширину, что и поле со списком.

Есть ли способ сделать раскрывающийся список более широким, чем поле со списком?

Этого я хочу достичь:

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

Я не могу изменить ширину combobox, потому что приложение представляет собой воссоздание старого унаследованного приложения, где некоторые вещи должны быть такими, какими они были раньше. (В этом случае combobox должен поддерживать его небольшим размером любой ценой)

4b9b3361

Ответ 1

Я считаю, что единственный способ сделать это с помощью публичного API - написать пользовательский интерфейс (есть два bugs, касающийся этого).

Если вы просто хотите что-то быстро и грязно, я нашел этот способ использовать детали реализации для этого (здесь):

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, и это может сработать для вас.

Или вы можете использовать код из первой связанной ошибки:

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());
  }
}

Ответ 3

Вот отличное решение от Santhosh Kumar, без необходимости возиться с пользовательским интерфейсом и другими неприятными вещами вроде этого!

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; 
    } 
}

Ответ 4

Вот хорошее решение от 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;

Надеюсь, что это полезно для использования в будущем!

Ответ 5

Похоже, вам нужно написать свой собственный ComboBoxUI.

Вот хороший пример здесь, который показывает, как это сделать.

Также обратите внимание, что метод, который вам, вероятно, будет интересен, - это метод createPopup(). Это метод, который создает всплывающее окно для поля со списком и где вы сможете его настроить.

Ответ 6

Возможно, вы захотите использовать метод setSize().

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