Java 如果在JComboBox弹出窗口可见时添加项目,则不会调整其大小

Java 如果在JComboBox弹出窗口可见时添加项目,则不会调整其大小,java,swing,popup,jcombobox,Java,Swing,Popup,Jcombobox,我对JComboBox弹出窗口有问题。我的JComboBox有一个自动完成的实现,就像google搜索框一样 所以,问题是,如果我添加或删除项目时,弹出窗口是可见的,它没有调整大小,我需要关闭并重新打开它。但是这场火灾是不可见的,可见的,所以我不能用这件事来表达我的真实想法 有没有一种方法可以根据包含的项目数“刷新”弹出窗口的大小,而不关闭并重新打开它 谢谢。在包含组合框的面板上调用revalidate()。这将导致部件根据其首选尺寸重新布置 这与在可见GUI上添加/删除组件的概念相同 编辑:

我对JComboBox弹出窗口有问题。我的JComboBox有一个自动完成的实现,就像google搜索框一样

所以,问题是,如果我添加或删除项目时,弹出窗口是可见的,它没有调整大小,我需要关闭并重新打开它。但是这场火灾是不可见的,可见的,所以我不能用这件事来表达我的真实想法

有没有一种方法可以根据包含的项目数“刷新”弹出窗口的大小,而不关闭并重新打开它

谢谢。

在包含组合框的面板上调用revalidate()。这将导致部件根据其首选尺寸重新布置

这与在可见GUI上添加/删除组件的概念相同

编辑:

重读你的问题。我不确定是否可以在弹出窗口打开时动态调整其大小,但您可以签出。它显示了如何覆盖弹出窗口的首选宽度。此代码在弹出菜单即将显示时执行。但是您可以使用这些概念访问弹出窗口并动态更改宽度

编辑2:

下面是一个显示基本概念的示例。弹出窗口将每2秒调整其宽度。但是,我不知道这是否有助于解决您的问题,因为如果您在弹出窗口中动态添加/删除项目,那么每次更改弹出窗口时,您都需要重新创建弹出窗口。这可能会导致弹出窗口隐藏/显示,这意味着您无论如何都需要有一点闪烁

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

public class ComboBoxExample extends JPanel implements ActionListener
{
    private JComboBox comboBox;

    public ComboBoxExample()
    {
        String[] petStrings = { "Select Pet", "Bird", "Cat", "Dog", "Rabbit", "Pig", "Other" };
        comboBox = new JComboBox( petStrings );
        add( comboBox, BorderLayout.PAGE_START );

        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;
        JList list = popup.getList();
        Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
        JScrollPane scrollPane = (JScrollPane)c;

        Dimension size = scrollPane.getSize();

        if (size.width > 20)
            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);
        Window popupWindow = SwingUtilities.windowForComponent(popup);

        //  For heavy weight popups you need to pack the window

        if (popupWindow != mainFrame)
            popupWindow.pack();
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame( "ComboBoxExample" );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        JComponent newContentPane = new ComboBoxExample();
        newContentPane.setOpaque( true );
        frame.setContentPane( newContentPane );
        frame.pack();
        frame.setVisible(true);
    }

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

下面是另一个在添加项目时更改宽度的示例:

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

public class ComboBoxExample2 extends JPanel implements ActionListener
{
    private JComboBox comboBox;

    public ComboBoxExample2()
    {
        String[] petStrings = { "A" };
        comboBox = new JComboBox( petStrings );
        comboBox.setPrototypeDisplayValue("A1111111111");
        add( comboBox, BorderLayout.PAGE_START );

        Timer timer = new javax.swing.Timer(2000, this);
        timer.start();
    }

    public void actionPerformed(ActionEvent e)
    {
        String text = comboBox.getItemAt( comboBox.getItemCount() - 1 ).toString();
        comboBox.addItem( text + "1");
        comboBox.showPopup();

        Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
        BasicComboPopup popup = (BasicComboPopup)child;
        JList list = popup.getList();
        Dimension preferred = list.getPreferredSize();
        preferred.width += 20; // allow for scrollbar
        int rowHeight = preferred.height / comboBox.getItemCount();
        int maxHeight = comboBox.getMaximumRowCount() * rowHeight;
        preferred.height = Math.min(preferred.height, maxHeight);

        Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
        JScrollPane scrollPane = (JScrollPane)c;

        scrollPane.setPreferredSize(preferred);
        scrollPane.setMaximumSize(preferred);

        Dimension popupSize = popup.getSize();
        popupSize.width = preferred.width;
        popupSize.height = preferred.height + 2;
        Component parent = popup.getParent();
        parent.setSize(popupSize);

        parent.validate();
        parent.repaint();

        Window mainFrame = SwingUtilities.windowForComponent(comboBox);
        Window popupWindow = SwingUtilities.windowForComponent(popup);

        //  For heavy weight popups you need to pack the window

        if (popupWindow != mainFrame)
            popupWindow.pack();

    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame( "ComboBoxExample2" );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        JComponent newContentPane = new ComboBoxExample2();
        newContentPane.setOpaque( true );
        frame.setContentPane( newContentPane );
        frame.pack();
        frame.setVisible(true);
    }

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

您确定要在AWT事件分派线程中对模型进行更改,然后触发正确的事件吗?我在insertString中进行更改,并删除自定义文档的方法。我很确定我触发了所有事件。这是一个真正的问题,几乎没有解决方案。我尝试重新验证组合框和弹出窗口,但似乎没有任何效果。我还尝试通过设置preferredSize来调整弹出窗口的高度,但新高度是在弹出窗口关闭后设置的…链接中的示例提供了一个弹出窗口侦听器,并在popupBecomeVisible事件期间工作,我尝试调整弹出窗口的大小,但不使弹出窗口不可见和可见。我在回答中提到,当弹出窗口即将显示时,代码会起作用。我建议您可以使用这里介绍的概念,因为它可以让您访问组成弹出菜单的组件。即获取弹出窗口,获取滚动窗格,调整滚动窗格的大小,并重新验证弹出窗口。我不知道它是否会起作用,但这就是我所能建议的。