Всплывающее окно JComboBox не изменяется, если я добавляю элемент, когда он виден

У меня проблема с всплывающим окном JComboBox. Мой JComboBox имеет реализацию автозаполнения, такую ​​​​как окно поиска Google.

Итак, проблема в том, что если я добавляю или удаляю элементы, когда всплывающее окно видно, его размер не изменяется, мне нужно закрыть и снова открыть его. Но этот огонь popupBecomeInvisible и popupBecomeVisible, поэтому я не могу использовать эти события для своей настоящей дельфина.

Есть ли способ «обновить» размер всплывающего окна в соответствии с количеством содержащихся в нем элементов, не закрывая и не открывая его снова?

Спасибо.


person blow    schedule 20.02.2011    source источник
comment
Вы уверены, что вносите изменения в модель в потоке отправки событий AWT и запускаете нужные события?   -  person Paŭlo Ebermann    schedule 20.02.2011
comment
Я вношу изменения в insertString и удаляю методы своего пользовательского документа. Я почти уверен, что запускаю все события.   -  person blow    schedule 20.02.2011
comment
Это реальная проблема, и для нее практически нет решения.   -  person m4heshd    schedule 06.07.2019


Ответы (2)


Вызовите revalidate() на панели, содержащей поле со списком. Это приведет к повторному расположению компонентов в соответствии с их предпочтительными размерами.

Это та же концепция, что и добавление/удаление компонента в видимом графическом интерфейсе.

Редактировать:

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

Редактировать 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();
            }
        });
    }
}
person camickr    schedule 20.02.2011
comment
Я пытаюсь перепроверить поле со списком и всплывающее окно, но ничего не работает. Я также пытаюсь изменить размер ВЫСОТЫ моего всплывающего окна, установив предпочтительный размер, но новая высота устанавливается после закрытия всплывающего окна... - person blow; 20.02.2011
comment
Пример в вашей ссылке предоставляет прослушиватель всплывающих окон и работает во время событий popupBecomeVisible, я пытаюсь изменить размер всплывающего окна БЕЗ сделать всплывающее окно невидимым и видимым. - person blow; 20.02.2011
comment
В своем ответе я упомянул, что код работает, когда всплывающее окно вот-вот появится. Я предполагал, что вы сможете использовать представленные там концепции, поскольку это дает вам доступ к компонентам, составляющим всплывающее меню. То есть получить всплывающее окно, получить область прокрутки, изменить размер области прокрутки и повторно подтвердить всплывающее окно. Я не знаю, сработает ли это, но это все, что я могу предложить. - person camickr; 20.02.2011

Вот еще один пример, который изменяет ширину по мере добавления элементов:

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();
            }
        });
    }
}
person camickr    schedule 20.02.2011