java - 阶梯式组合框刷新

标签 java swing jcombobox

一个Stepped ComboBox使下拉弹出窗口比文本字段更宽非常有用。但是,当新内容添加到列表中时,弹出窗口将恢复其初始宽度。

默认

enter image description here

刷新后(新元素)

enter image description here

SSCCE

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;

public class SteppedComboBoxRefresh extends JFrame {
    private List<String> list;
    private final SteppedComboBox combo;

    public SteppedComboBoxRefresh() {
        super("SteppedComboBox Refresh");

        this.list = new ArrayList<String>(Arrays.asList(new String[]{
                "AAA", "AAAAAA"
        }));

        this.combo = new SteppedComboBox(this.list.toArray());
        this.combo.setDimensions(50);

        JButton addButton = new JButton("Add longer string");
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                list.add(list.get(list.size()-1) + "AAA");
                combo.setModel(new DefaultComboBoxModel(list.toArray()));
                combo.setDimensions(50);
            }
        });

        getContentPane().setLayout(new FlowLayout());
        getContentPane().add(this.combo);
        getContentPane().add(addButton);
    }

    public static void main (String args[]) {
        SteppedComboBoxRefresh f = new SteppedComboBoxRefresh();
        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.setSize (300, 100);
        f.setVisible(true);
    }
}

class SteppedComboBoxUI extends MetalComboBoxUI {
    @Override
    protected ComboPopup createPopup() {
        BasicComboPopup popup = new BasicComboPopup( this.comboBox ) {

            @Override
            public void show() {
                Dimension popupSize = ((SteppedComboBox)this.comboBox).getPopupSize();
                popupSize.setSize( popupSize.width,
                        getPopupHeightForRowCount( this.comboBox.getMaximumRowCount() ) );
                Rectangle popupBounds = computePopupBounds( 0,
                        this.comboBox.getBounds().height, popupSize.width, popupSize.height);
                this.scroller.setMaximumSize( popupBounds.getSize() );
                this.scroller.setPreferredSize( popupBounds.getSize() );
                this.scroller.setMinimumSize( popupBounds.getSize() );
                this.list.invalidate();
                int selectedIndex = this.comboBox.getSelectedIndex();
                if ( selectedIndex == -1 ) {
                    this.list.clearSelection();
                } else {
                    this.list.setSelectedIndex( selectedIndex );
                }
                this.list.ensureIndexIsVisible( this.list.getSelectedIndex() );
                setLightWeightPopupEnabled( this.comboBox.isLightWeightPopupEnabled() );

                show( this.comboBox, popupBounds.x, popupBounds.y );
            }
        };
        popup.getAccessibleContext().setAccessibleParent(this.comboBox);
        return popup;
    }
}

class SteppedComboBox extends JComboBox {
    protected int popupWidth;

    public SteppedComboBox(ComboBoxModel aModel) {
        super(aModel);
        setUI(new SteppedComboBoxUI());
        this.popupWidth = 0;
    }

    public SteppedComboBox(final Object[] items) {
        super(items);
        setUI(new SteppedComboBoxUI());
        this.popupWidth = 0;
    }

    public SteppedComboBox(Vector items) {
        super(items);
        setUI(new SteppedComboBoxUI());
        this.popupWidth = 0;
    }

    public void setPopupWidth(int width) {
        this.popupWidth = width;
    }

    public Dimension getPopupSize() {
        Dimension size = getSize();
        if (this.popupWidth < 1) {
            this.popupWidth = size.width;
        }
        return new Dimension(this.popupWidth, size.height);
    }

    public void setDimensions(int width) {
        Dimension d = getPreferredSize();
        setPreferredSize(new Dimension(width, d.height));
        setPopupWidth(d.width);
    }
}

最佳答案

ComboBox 仍使用其之前的 PreferredSize。需要将首选大小设置回null,以便我们获得列表中新内容的首选大小。

void javax.swing.JComponent.setPreferredSize(Dimension preferredSize)

Sets the preferred size of this component. If preferredSize is null, the UI will be asked for the preferred size.

public void setDimensions(int width) {
    setPreferredSize(null);
    Dimension d = getPreferredSize();
    setPreferredSize(new Dimension(width, d.height));
    setPopupWidth(d.width);
}

结果

enter image description here

关于java - 阶梯式组合框刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31344538/

相关文章:

java - Java 中的 ActionPerformed 方法

java - 共享两个组合框的数据源

java - 检查 JComboBox 值

java - 绘制可拖动的文本框

java - 使用文本文件填充 JCombobox

java - 使用arraylist而不是array

java - Spring servlet 映射——没有 css 或 jsp!

java - Spring Security仅适用于最高优先级顺序

Java 1.8 拒绝解析带有美国/阿留申 (HAST) 时区的日期?

java - 如何将 MouseListener 添加到 JList 项目?