JScrollpane 使用可变大小的内容调整大小

发布于 2024-10-16 10:20:27 字数 4928 浏览 0 评论 0原文

我的可调整大小的 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,它显式设置视口视图的首选大小,从而触发组件验证。但是,调整大小会导致滚动条抖动。有没有更干净的方法来做到这一点?

编辑:感谢 camickr 提供的 ScrollablePanel 链接,我修改了 JPanel 类以实现 Scrollable,并动态更改 getScrollableTracksViewportWidth() 的返回值。

当视口很大时,我为 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;
        }

    }
}

My resizable JScrollPane's content has a minimum width. If the JScrollPane is smaller than this width, horizontal scroll bars should appear. If it's greater than this width, the viewport content should expand to fill up the entire viewport.

Seems like a simple concept, and I've got something that's working, but it feels like a 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();
        }
    }
}

Resizing the dialog triggers the ComponentListener, which explicitly sets the preferred size of the viewport view, triggering component validation. However, resizing causes jittery scroll bars. Is there a cleaner way to do this?

EDIT: thanks to camickr for the ScrollablePanel link, I've modified my JPanel class to implement Scrollable, and dynamically change the return value for getScrollableTracksViewportWidth().

When the viewport is big, I return true for getScrollableTracksViewportWidth(), telling the JScrollPane to fill the view with my component. When the viewport is small, I return false, so the scrollbars appear.

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;
        }

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

回忆追雨的时光 2024-10-23 10:20:27

不确定,但您也许可以使用可滚动面板。您可以配置组件调整大小(尝试使用 STRETCH)。该代码适用于组件的首选尺寸而不是最小尺寸,因此它可能不完全是您想要的。

Not sure, but you might be able to use the Scrollable Panel. You can configure the component resizing (try using STRETCH). The code works on the preferred size of the component not the minimum size so it may not be exactly what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文