java - 在不影响外观的情况下更改 JComboBox 弹出窗口大小?

标签 java swing jcombobox

我正在寻找一种改变 JComboBox 弹出窗口宽度的方法。基本上,弹出窗口应该与组合框条目所需的最宽一样宽,而不是组合框当前的宽度。

我知道如何实现此目的的唯一方法是创建 ComboBoxUI 的自定义实例并将其设置在 JComboBox 上(示例代码演示了目标:Top Combobox 显示宽弹出窗口,Bottom 是默认行为)。然而,由于这取代了 ComboBox 的 UI,它在某些 L&F 上可能看起来很奇怪(例如,对于 WinXP Luna 主题,ComboBox 看起来像经典主题)。

有没有办法以 L&F 不可知论的方式实现这种行为?

public class CustomCombo extends JComboBox {

    final static class CustomComboUI 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;
        }
    }

    {
        setUI(new CustomComboUI());
    }

    public static void main(String[] argv) {
        try {
            final String className = UIManager.getSystemLookAndFeelClassName();
            UIManager.setLookAndFeel(className);
        } catch (final Exception e) {
            // ignore
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createGUI();    
            }
        });
    }

    public static void createGUI() {
        JComboBox combo1 = new CustomCombo();
        JComboBox combo2 = new JComboBox();
        JPanel panel = new JPanel();
        JFrame frame = new JFrame("Testframe");
        combo1.addItem("1 Short item");
        combo1.addItem("2 A very long Item name that should display completely in the popup");
        combo1.addItem("3 Another short one");
        combo2.addItem("1 Short item");
        combo2.addItem("2 A very long Item name that should display completely in the popup");
        combo2.addItem("3 Another short one");
        panel.setPreferredSize(new Dimension(30, 50));
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gc;
        gc = new GridBagConstraints(0, 0, 1, 1, 1D, 0D, GridBagConstraints.WEST,
                GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0);
        panel.add(combo1, gc);
        gc = new GridBagConstraints(0, 1, 1, 1, 1D, 0D, GridBagConstraints.WEST,
                GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0);
        panel.add(combo2, gc);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

}

最佳答案

  1. 通过使用 GBC,您可以在容器中设置适当的高度和重量

  2. @trashgod 提到的下一种方法是使用 JComboBox.setPrototypeDisplayValue()

  3. 设置 PreferredSize
  4. 使用 Combo Box Popup通过@camickr

  5. 派生 JPopup 必须使用 pack() 否则太难改变它的 Dimension easill

    <

.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class ComboBoxExample extends JPanel implements ActionListener {
//http://stackoverflow.com/a/5058210/714968

    private static final long serialVersionUID = 1L;
    private JComboBox comboBox;

    public ComboBoxExample() {
        String[] petStrings = {"Select Pet", "Bird", "Cat", "Dog", "Rabbit", "Pig", "Other"};
        comboBox = new JComboBox(petStrings);
        comboBox.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        add(comboBox, BorderLayout.PAGE_START);
        JFrame frame = new JFrame("ComboBoxExample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(comboBox);
        frame.setName("ComboBoxExample");
        frame.setLocation(150, 150);
        frame.pack();
        frame.setVisible(true);
        Timer timer = new javax.swing.Timer(2000, this);
        timer.start();
    }

    public void actionPerformed(ActionEvent e) {
        comboBox.showPopup();
        Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
        BasicComboPopup popup = (BasicComboPopup) child;
        popup.setName("BasicComboPopup");
        JList list = popup.getList();
        Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
        JScrollPane scrollPane = (JScrollPane) c;
        Dimension size = scrollPane.getSize();
        if (size.width > 30) {
            size.width -= 5;
        }
        scrollPane.setPreferredSize(size);
        scrollPane.setMaximumSize(size);
        Dimension popupSize = popup.getSize();
        popupSize.width = size.width;
        Component parent = popup.getParent();
        parent.setSize(popupSize);
        parent.validate();
        parent.repaint();
        Window mainFrame = SwingUtilities.windowForComponent(comboBox);
        //Returns the first Window ancestor of c, or null if c is not contained inside a Window.
        System.out.println(mainFrame.getName());
        Window popupWindow = SwingUtilities.windowForComponent(popup);
        System.out.println(popupWindow.getName());
        Window popupWindowa = SwingUtilities.windowForComponent(c);
        System.out.println(popupWindowa.getName());

        Window mainFrame1 = SwingUtilities.getWindowAncestor(comboBox);
        //Returns the first Window ancestor of c, or null if c is not contained inside a Window.
        System.out.println(mainFrame1.getName());
        Window popupWindow1 = SwingUtilities.getWindowAncestor(popup);
        System.out.println(popupWindow1.getName());

        Component mainFrame2 = SwingUtilities.getRoot(comboBox);
        //Returns the root component for the current component tree.
        System.out.println(mainFrame2.getName());
        Component popupWindow2 = SwingUtilities.getRoot(popup);
        System.out.println(popupWindow2.getName());
        //  For heavy weight popups you need always to pack() for the window
        if (popupWindow != mainFrame) {
            popupWindow.pack();
        }
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                ComboBoxExample comboBoxExample = new ComboBoxExample();
            }
        });
    }
}

关于java - 在不影响外观的情况下更改 JComboBox 弹出窗口大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11435138/

相关文章:

java - 重命名 Swing 组件使用的文件

java - 从另一个 JFrames 构造函数创建 JFrame

java - GridBagLayout 中的 JComboBox 宽度问题

java - 将项目添加到 JComboBox

java - 如何检索和编辑您使用代码创建的正确 TextView ,而不是使用 main.xml?

java - jnlp 控制台语句重定向到服务器

java - 如何让记录器包裹在 slf4j 中?

java - 对一组 jButton 实现 ActionListener 时出现问题

java - Thread 中的 repaint() 导致 CPU 使用率很高

java - ItemListener.itemStateChanged() 中取消选择的项目