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

时间:2011-02-27 10:56:29

标签: java swing view jscrollpane viewport

我有一个包含垂直Box的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仅供参考,因为那些可能会关心的人。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

类似的东西:

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