Как я могу изменить ширину выпадающего списка JComboBox? - PullRequest
27 голосов
/ 05 июня 2009

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

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

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

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

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

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

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

Ответы [ 7 ]

16 голосов
/ 12 июня 2009
14 голосов
/ 03 ноября 2011

Вот отличное решение от 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; 
    } 
}
14 голосов
/ 05 июня 2009

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

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

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());
  }
}
5 голосов
/ 17 апреля 2012

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

Надеюсь, это пригодится для дальнейшего использования!

1 голос
/ 05 июня 2009

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

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

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

0 голосов
/ 17 мая 2018

Здесь у вас есть простой кусок кода без расширений 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);
                    }                       
                };
            }
        });
0 голосов
/ 29 января 2013

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

combo.setSize(200, combo.getPreferredSize().height);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...