JScrollPane 在顶部添加 JPanel 并保持当前滚动视图

发布于 2024-10-19 13:39:45 字数 2855 浏览 5 评论 0原文

我有一个包含垂直框的 JScrollPane。我正在 Box 的顶部插入新的 JPanel。如果我使用滚动条向下滚动,我希望当前视图保留在我向下滚动到的位置。例如,如果框中有 50 个面板并使用滚动条查看面板 20,则即使在顶部添加了其他框,我也希望视图保留在框 20 上。此外,如果我使用滚动条向上滚动到顶部,我希望视图在添加新面板时显示它们。知道如何做到这一点吗?

顺便说一句,没有必要使用 JScrollPane 或 Box。示例代码只是为了帮助解释我想要做什么。

示例代码:

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

public class TestScrollPane extends JFrame {

    JScrollPane scrollPane;
    Box box;
    private static int panelCount = 0;

    public TestScrollPane() {
        setPreferredSize(new Dimension(200, 400));
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        scrollPane = new JScrollPane();
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.getVerticalScrollBar().setUnitIncrement(15);
        box = Box.createVerticalBox();
        scrollPane.getViewport().add(box);

        this.add(scrollPane);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        Timer t = new Timer(500, new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                box.add(new TestPanel(), 0);
                scrollPane.validate();
            }
        });
        t.setRepeats(true);
        t.start();
    }

    public class TestPanel extends JPanel {

        int myId = panelCount++;

        public TestPanel() {
            this.setLayout(new GridBagLayout());
            this.setBorder(BorderFactory.createBevelBorder(1));
            JLabel label = new JLabel("" + myId);
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setVerticalAlignment(JLabel.CENTER);

            this.setMaximumSize(new Dimension(100, 100));
            this.setPreferredSize(new Dimension(100, 100));

            this.add(label);
        }
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                TestScrollPane testScrollPane = new TestScrollPane();
            }
        });
    }
}

编辑: 这就是我最终更改代码的方式。我觉得自己有些愚蠢,因为没有看到显而易见的事情。不管怎样,感谢那些提供帮助的人。

            public void actionPerformed(ActionEvent ae) {
                Point view = scrollPane.getViewport().getViewPosition();
                TestPanel panel = new TestPanel();
                box.add(panel, 0);
                scrollPane.validate();
                if (view.y != 0) {
                    view.y += panel.getHeight();
                    scrollPane.getViewport().setViewPosition(view);
                }
            }

顺便说一句,我已将这个问题交叉发布到 http://www.coderanch.com/t/528829/GUI/java/JScrollPane-adding-JPanels-at-top#2398276仅供那些可能关心的人参考。

I have a JScrollPane that contains a vertical Box. I'm inserting new JPanel's at the top of Box. If I use the scrollbar to scroll down I'd like for the current view to remain where I scrolled down to. For example, if I have 50 panels in the box and use the scrollbar to view panel 20, I'd like the view to remain on box 20 even though other boxes are added on top. Additionally, if I use the scrollbar to scroll back up to the top I'd like the view to display new panels as they are added. Any idea how to do this?

BTW, it isn't necessary to use a JScrollPane or a Box. The example code is just to help explain what I am trying to do.

Example code:

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

public class TestScrollPane extends JFrame {

    JScrollPane scrollPane;
    Box box;
    private static int panelCount = 0;

    public TestScrollPane() {
        setPreferredSize(new Dimension(200, 400));
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        scrollPane = new JScrollPane();
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.getVerticalScrollBar().setUnitIncrement(15);
        box = Box.createVerticalBox();
        scrollPane.getViewport().add(box);

        this.add(scrollPane);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        Timer t = new Timer(500, new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                box.add(new TestPanel(), 0);
                scrollPane.validate();
            }
        });
        t.setRepeats(true);
        t.start();
    }

    public class TestPanel extends JPanel {

        int myId = panelCount++;

        public TestPanel() {
            this.setLayout(new GridBagLayout());
            this.setBorder(BorderFactory.createBevelBorder(1));
            JLabel label = new JLabel("" + myId);
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setVerticalAlignment(JLabel.CENTER);

            this.setMaximumSize(new Dimension(100, 100));
            this.setPreferredSize(new Dimension(100, 100));

            this.add(label);
        }
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                TestScrollPane testScrollPane = new TestScrollPane();
            }
        });
    }
}

EDIT:
This is how I ended up changing the code. I feel somewhat foolish for not seeing the obvious. Anyways, thanx to those that helped.

            public void actionPerformed(ActionEvent ae) {
                Point view = scrollPane.getViewport().getViewPosition();
                TestPanel panel = new TestPanel();
                box.add(panel, 0);
                scrollPane.validate();
                if (view.y != 0) {
                    view.y += panel.getHeight();
                    scrollPane.getViewport().setViewPosition(view);
                }
            }

BTW, I had cross posted this question to http://www.coderanch.com/t/528829/GUI/java/JScrollPane-adding-JPanels-at-top#2398276 Just FYI for those that might care.

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

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

发布评论

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

评论(2

柏林苍穹下 2024-10-26 13:39:45

您可以获取要使其可见的组件的边界(使用 JComponent 的 getBounds 方法),并将其用作 JViewPort 的 rollRectToVisible 方法的输入。

You could get the bounds of the component you want to make visible (using JComponent's getBounds method), and use that as an input to JViewPort's scrollRectToVisible method.

梦醒灬来后我 2024-10-26 13:39:45

像这样的东西:

    Timer t = new Timer(1000, new ActionListener() {

        public void actionPerformed(ActionEvent ae) {
            TestPanel panel = new TestPanel();
            box.add(panel, 0);
            JViewport vp = scrollPane.getViewport();
            Point p = vp.getViewPosition();
            p.y += panel.getPreferredSize().height;
            scrollPane.revalidate();
            vp.setViewPosition(p);
        }
    });

Something like:

    Timer t = new Timer(1000, new ActionListener() {

        public void actionPerformed(ActionEvent ae) {
            TestPanel panel = new TestPanel();
            box.add(panel, 0);
            JViewport vp = scrollPane.getViewport();
            Point p = vp.getViewPosition();
            p.y += panel.getPreferredSize().height;
            scrollPane.revalidate();
            vp.setViewPosition(p);
        }
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文