JScrollPane随可变大小的内容调整大小

13

我的可调整大小的JScrollPane内容有一个最小宽度。如果JScrollPane比这个宽度小,则应该出现水平滚动条。如果它比这个宽度大,则视口内容应扩展以填充整个视口。

这似乎是一个简单的概念,我已经得到了一些可以工作的东西,但感觉像是一个hack:

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,该监听器会显式设置视口视图的首选大小,从而触发组件验证。然而,调整大小会导致滚动条抖动。有没有更好的方法来做到这一点?
编辑:感谢camickr提供ScrollablePanel链接,我修改了我的JPanel类以实现Scrollable,并动态更改getScrollableTracksViewportWidth()的返回值。
当视口很大时,我返回true以告诉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;
        }

    }
}
1个回答

7

我不确定,但你可能可以使用可滚动面板。您可以配置组件的调整大小(尝试使用STRETCH)。 该代码适用于组件的首选大小而非最小大小,因此可能与您想要的不完全相符。


1
太棒了!我没有使用ScrollablePanel类,但是那个页面上建议动态更改Scrollable#getScrollableTracksViewportWidth的返回值的方法完美地起作用了。 - Sam Barnum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接