Изменение размера панели с потоковой компоновкой не вызывает полосы прокрутки

У меня есть содержащая панель JPanel с Flow Layout, содержащая панель находится в JScrollPane, содержащая панель >содержащая панель содержит множество других внутренних панелей JPanel. Все внутренние панели имеют одинаковые размеры. Если панелей больше, то содержащая панель может удерживать свою ширину, тогда они располагаются по сетке вниз, а если панелей больше, то содержащая панель > может удерживать свою высоту, тогда внутренние панели выравниваются по одной и той же сетке, за исключением последней строки, которая центрируется с предыдущей строкой.

Пока я изменяю размер диалогового окна, содержащая панель расширяется, и макет потока макета выполняет свои обязанности, но полосы прокрутки не появляются, хотя размер панели превышает границы JScrollPane.

Как управлять внешним видом полос прокрутки при динамическом изменении размера содержащей панели?

что касается изображений, они должны подвести итог:

альтернативный текст

После увеличения ширины диалогового окна:

альтернативный текст

Адам


person TacB0sS    schedule 05.10.2010    source источник
comment
Самостоятельный минимальный образец кода может помочь людям легче понять вашу проблему.   -  person Michael Myers    schedule 06.10.2010
comment
Что вы подразумеваете под сеткой вниз? Скриншоты тоже не помешали бы. И вообще, вы используете либо динамическую верстку, либо прокрутку, но не то и другое одновременно.   -  person Geoffrey Zheng    schedule 06.10.2010
comment
Забавно, что я никогда не использовал FlowLayout, поскольку он слишком примитивен для любого нетривиального графического интерфейса, поэтому я не понял, что вы описываете его поведение по умолчанию.   -  person Geoffrey Zheng    schedule 07.10.2010


Ответы (1)


Вам нужно сделать содержащую панель Scrollable и установить предпочтительный размер прокручиваемого окна просмотра в соответствии с шириной.

import java.awt.*;
import javax.swing.*;

public class Test
{
    public static void main(String args[])
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                JPanel container = new ScrollablePanel();
                container.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
                for( int i = 0; i < 20; ++i )
                {
                    JPanel p = new JPanel();
                    p.setBorder(BorderFactory.createLineBorder(Color.RED));
                    p.setPreferredSize(new Dimension(50, 50));
                    p.add(new JLabel("" + i));
                    container.add(p);
                }

                JScrollPane scroll = new JScrollPane(container);
                scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

                JFrame f = new JFrame("Test");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                    
                f.getContentPane().add(scroll);                    
                f.pack();
                f.setSize(250, 300);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

class ScrollablePanel extends JPanel implements Scrollable
{
    public Dimension getPreferredSize()
    {
        return getPreferredScrollableViewportSize();
    }

    public Dimension getPreferredScrollableViewportSize()
    {
        if( getParent() == null )
            return getSize();
        Dimension d = getParent().getSize();
        int c = (int)Math.floor((d.width - getInsets().left - getInsets().right) / 50.0);
        if( c == 0 )
            return d;
        int r = 20 / c;
        if( r * c < 20 )
            ++r;
        return new Dimension(c * 50, r * 50);
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
    {
        return 50;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
    {
        return 10;
    }

    public boolean getScrollableTracksViewportHeight()
    {
        return false;
    }

    public boolean getScrollableTracksViewportWidth()
    {
        return getParent() != null ? getParent().getSize().width > getPreferredSize().width : true;
    }
}

Все числа жестко закодированы для простоты, но вы должны уловить идею.

person Geoffrey Zheng    schedule 07.10.2010
comment
ВАУ, забрал меня навсегда, getPreferredScrollableViewportSize() не вызывался независимо от того, что я делал, вызывался только getPreferredSize(), поэтому я начал с нуля, и тогда это сработало, расстроенный, я сравнил два кода, и, по-видимому, NetBeans генерирует setPreferredSize(w,h) в некоторых случаях, и как только это установлено, макет окна просмотра пропускает метод. Хорошая поездка, это был жук. Спасибо за помощь, кажется, я получил все, что нужно. - person TacB0sS; 08.10.2010
comment
Вот почему я не использую конструктор графического интерфейса :) - person Geoffrey Zheng; 08.10.2010