4

I have a JPanel in a JScrollPane. The JPanel contains multiple JTextAreas vertically.

I like to keep the scroll of the scrollpane to the top whenever the page is refreshed. Currently, the scroll always starts from the bottom.

this is my current code and it doesn't work..

    panel.invalidate();
    panel.revalidate();
    panel.repaint();
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ((JPanel) panel).setLocation(new Point(0, 0));
        }
    });

I've also tried adding this code below to scrollpane, but it doesn't work..

scrollPanel.getViewport().setViewPosition( new Point(0, 0) );

I've looked into other stackoverflow questions and they use Jtextarea inside Jscrollpane (they solved it using setCaretPosition(0), however I can't use the same function to the panel). In my case, there is an extra layer.

How can I solve this..?

EDIT**

Based on advice from Pavlo Viazovskyy, I've also tried this below and it still doesn't work for me.. :(

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            scrollPane.getVerticalScrollBar().setValue(0);
        }
    });
In-young Choung
  • 779
  • 2
  • 8
  • 22
  • If you will use setCaretPosition(0) on JScrollPane which holds your JPanel it should do the trick. – Pavlo Viazovskyy Mar 22 '17 at 19:36
  • Thank you for your input. JScrollPane doesn't have the method; setCaretPosition().. Is there a way to use it on JScrollPane? – In-young Choung Mar 22 '17 at 19:51
  • Got it. I hope [this post](http://stackoverflow.com/questions/291115/java-swing-using-jscrollpane-and-having-it-scroll-back-to-top) will help you. – Pavlo Viazovskyy Mar 22 '17 at 19:55
  • @PavloViazovskyy I got a new idea from the post you shared but it still didn't work for me. I updated the question just to show the methods I've tried so far. Thank you. – In-young Choung Mar 22 '17 at 20:14
  • 1
    Setting the viewport position should work. Make sure the code is invoked in the SwingUtilities.invokeLater(). If you need more help then post a proper [mcve] demonstating the problem. – camickr Mar 22 '17 at 20:15
  • `panel#scrollRectToVisible(new Rectangle(0, 0, 1, 1))` – MadProgrammer Mar 22 '17 at 21:00

2 Answers2

7

Thank you very much for all the comments. sorry I didn't give a full proper example in the question as there were too many different classes involved..

In my case, textareas inside Panel inside ScrollPane, I made the scroll to the top by default by using setViewPosition method to scrollPane in the invokelater method.

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        scrollPane.getViewport().setViewPosition( new Point(0, 0) );
    }
});
In-young Choung
  • 779
  • 2
  • 8
  • 22
2

For when you don't have direct access to the JScrollPane, you can simply use JComponent#scrollRectToVisible

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class ScrollTest {

    public static void main(String[] args) {
        new ScrollTest();
    }

    public ScrollTest() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.add(new JScrollPane(new BigPane()));
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BigPane extends JPanel {

        public BigPane() {
            setLayout(new BorderLayout());
            JButton scroll = new JButton("Scroll to top");
            add(scroll, BorderLayout.SOUTH);
            scroll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    scrollRectToVisible(new Rectangle(0, 0, 1, 1));
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

    }

}

Yes, you could walk the component hierarchy till you found a JViewport, but this method does it for you.

Just remember though, the Rectangle is relative to the component which called the method, so if I used the JButton instead, it would try and make the JButton visible, not the panel

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366