Изменение размера JScrollpane с содержимым переменного размера

У моего изменяемого размера содержимого JScrollPane минимальная ширина. Если JScrollPane меньше этой ширины, должны появиться горизонтальные полосы прокрутки. Если он больше этой ширины, содержимое области просмотра должно расшириться, чтобы заполнить всю область просмотра.

Кажется, простая идея, и у меня есть кое-что, что работает, но это похоже на хакерство:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

public class SSBTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final Component view = new MyView();
                final JScrollPane jScrollPane = new JScrollPane(view);
                jScrollPane.addComponentListener(new ComponentAdapter() {
                    @Override
                    public void componentResized(final ComponentEvent e) {
                        final Dimension minimumSize = view.getMinimumSize();
                        final int width = Math.max(minimumSize.width, jScrollPane.getViewport().getWidth());
                        view.setPreferredSize(new Dimension(width, minimumSize.height));
                    }
                });
                showInDialog(jScrollPane);
            }
        });
    }

    private static void showInDialog(final JScrollPane jScrollPane) {
        final JDialog dialog = new JOptionPane(jScrollPane).createDialog("JScrollPane Resize Test");
        dialog.setResizable(true);
        dialog.setModal(true);
        dialog.setVisible(true);
        System.exit(0);
    }

    private static final class MyView extends JPanel {
        @Override
        protected void paintComponent(final Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawString("Dimensions are " + getSize(), 10, 20);
            g.drawRect(0, 0, getMinimumSize().width-1, getMinimumSize().height-1);
            g.setColor(Color.BLUE);
            g.drawRect(0, 0, getPreferredSize().width-1, getPreferredSize().height-1);
        }

        @Override
        public Dimension getMinimumSize() {
            return new Dimension(200, 200);
        }

        @Override
        public Dimension getPreferredSize() {
            return super.getPreferredSize();
        }
    }
}

Изменение размера диалогового окна запускает ComponentListener, который явно устанавливает предпочтительный размер представления области просмотра, запуская проверку компонента. Однако изменение размера вызывает дрожание полос прокрутки. Есть ли более чистый способ сделать это?

EDIT: спасибо camickr за ссылку ScrollablePanel, я ' я изменил свой класс JPanel для реализации Scrollable и динамически изменил возвращаемое значение для getScrollableTracksViewportWidth ().

Когда область просмотра большая, я возвращаю true для getScrollableTracksViewportWidth () , сообщая JScrollPane, чтобы заполнить представление моим компонентом. Когда окно просмотра маленькое, я возвращаю false , поэтому появляются полосы прокрутки.

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

public class SSBTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final Component view = new MyView();
                final JScrollPane jScrollPane = new JScrollPane(view);
                showInDialog(jScrollPane);
            }
        });
    }

    private static void showInDialog(final JScrollPane jScrollPane) {
        final JDialog dialog = new JOptionPane(jScrollPane).createDialog("JScrollPane Resize Test");
        dialog.setResizable(true);
        dialog.setModal(true);
        dialog.setVisible(true);
        System.exit(0);
    }

    private static final class MyView extends JPanel implements Scrollable {
        @Override
        protected void paintComponent(final Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawString("MyView: " + getWidth() + "x" + getHeight(), 10, 20);
            g.drawRect(0, 0, getMinimumSize().width-1, getMinimumSize().height-1);
            g.setColor(Color.BLUE);
            g.drawRect(0, 0, getPreferredSize().width-1, getPreferredSize().height-1);
            g.drawString("Preferred/Minimum Size", 10, getPreferredSize().height/2);
            g.setColor(Color.GREEN);
            g.drawLine(0, 0, getWidth(), getHeight());
        }

        @Override
        public Dimension getMinimumSize() {
            return new Dimension(200, 200);
        }

        @Override
        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

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

        public int getScrollableBlockIncrement(final Rectangle visibleRect, final int orientation, final int direction) {
            return visibleRect.width;
        }

        public boolean getScrollableTracksViewportWidth() {
            final Container viewport = getParent();
            return viewport.getWidth() > getMinimumSize().width;
        }

        public boolean getScrollableTracksViewportHeight() {
            return true;
        }

    }
}
12
задан Sam Barnum 10 February 2011 в 17:51
поделиться