Jak Mogę zmienić szerokość rozwijanej listy JComboBox?

Mam edytowalny JComboBox, który zawiera listę wartości pojedynczych liter. Z tego powodu combobox jest bardzo mały.

Każda litera ma specjalne znaczenie, które czasami nie jest jasne dla użytkownika w przypadku rzadko używanych liter. Z tego powodu stworzyłem własny ListCellRenderer, który pokazuje znaczenie każdej litery z rozwijanej listy.

Niestety to wyjaśnienie nie pasuje do rozwijanego menu, ponieważ jest małe, ponieważ ma taką samą szerokość jak combobox.

Czy jest jakiś sposób, aby lista rozwijana była szersza niż combobox?

Oto, co chcę osiągnąć:

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

Nie mogę zmienić szerokości comboboxu, ponieważ aplikacja jest odtworzeniem starej, starszej aplikacji, w której niektóre rzeczy muszą być dokładnie takie, jakie były wcześniej. (W tym przypadku combobox musi za wszelką cenę zachować swój mały rozmiar)

Author: Daniel Rikowski, 2009-06-05

6 answers

Uważam, że jedynym sposobem, aby to zrobić z publicznym API jest napisanie niestandardowego interfejsu użytkownika (są dwa bugs radzenie sobie z tym).

Jeśli chcesz po prostu czegoś szybkiego i brudnego, znalazłem ten sposób, aby użyć szczegółów implementacji do tego (tutaj):

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

Włóż to do PopupMenuListener i to może zadziałać dla Ciebie.

Lub możesz użyć kodu z pierwszego linkowanego błędu :

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());
  }
}
 17
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-05 14:21:17

Oto świetne rozwiązanie autorstwa Santhosh Kumar, bez potrzeby bałaganu z interfejsami i innymi paskudnymi rzeczami!

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; 
    } 
}
 15
Author: Shlomi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-03 11:38:14

Oto ładne rozwiązanie z tutiez .

Przed ustawieniem wymiaru wyskakującej listy, pobiera z niej największy element i oblicza szerokość potrzebną do jego całkowitego wyświetlenia.

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

    }
}

Powyższy kod ma już główną stronę do szybkiego testu. Ale zauważ, że poniższe stwierdzenie może być dostosowane do około 20 jeśli chcesz mieć przewijanie pionowe.

return widest + 5;

Mam nadzieję, że jest to przydatne w przyszłości!

 7
Author: rafaelrezend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-31 13:13:07

Wygląda na to, że będziesz musiał napisać swój własny ComboBoxUI .

Jest dobry przykład tutaj , który pokazuje, jak to osiągnąć.

Zauważ również, że metoda, którą prawdopodobnie będziesz zainteresowany, to metoda createPopup(). Jest to metoda, która tworzy wyskakujące okienko dla pola kombi i gdzie można go dostosować.

 1
Author: thedude19,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-05 14:10:22

Możesz użyć metody setSize().

combo.setSize(200, combo.getPreferredSize().height);
 0
Author: Ned,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 23:51:38

Tutaj masz prosty fragment kodu bez rozszerzeń JComboBox ani innych klas

W tym przykładzie z listy rozwijanej zawsze wynosi 500. Możesz również zmodyfikować wysokość lub lokalizację.

        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
Author: josepmra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-16 21:53:15