Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JScrollPane - Smooth Scrolling

I have a JScrollPane with a moderately high block increment (125). I would like to apply smooth/slow scrolling to it so it doesn't jump (or skip) when scrolling. How can I do this?

I was thinking of scrolling like Windows 8.

Any help would be greatly appreciated!

like image 439
Ramus Avatar asked Nov 25 '12 11:11

Ramus


People also ask

How do I make my JScrollPane scroll faster?

Just use the reference to your JScrollPane object, get the vertical scroll bar from it using getVerticalScrollBar , and then call setUnitIncrement on it, like this: myJScrollPane. getVerticalScrollBar(). setUnitIncrement(16);

What is the difference between JScrollPane and scrollbar?

A JScrollBar is a component and it doesn't handle its own events whereas a JScrollPane is a Container and it handles its own events and performs its own scrolling.

How do I scroll to top smooth in CSS?

Set the Stage: Basic content HTML We also add id="top" to the <header> and use that anchor as the href value for the back to top link. If you only wanted to scroll to the top of <main> you can move the id, or also attach it to an existing id near the top of your page.


1 Answers

You could use a javax.swing.Timer during the scroll to achieve the smooth scrolling effect. If you are triggering this from outside the component, somthing like this will work (where component is the component within the JScrollPane):

final int target = visible.y;
final Rectangle current = component.getVisibleRect();
final int start = current.y;
final int delta = target - start;
final int msBetweenIterations = 10;

Timer scrollTimer = new Timer(msBetweenIterations, new ActionListener() {
    int currentIteration = 0;
    final long animationTime = 150; // milliseconds
    final long nsBetweenIterations = msBetweenIterations * 1000000; // nanoseconds
    final long startTime = System.nanoTime() - nsBetweenIterations; // Make the animation move on the first iteration
    final long targetCompletionTime = startTime + animationTime * 1000000;
    final long targetElapsedTime = targetCompletionTime - startTime;

    @Override
    public void actionPerformed(ActionEvent e) {
        long timeSinceStart = System.nanoTime() - startTime;
        double percentComplete = Math.min(1.0, (double) timeSinceStart / targetElapsedTime);

        double factor = getFactor(percentComplete);
        current.y = (int) Math.round(start + delta * factor);
        component.scrollRectToVisible(current);
        if (timeSinceStart >= targetElapsedTime) {
            ((Timer) e.getSource()).stop();
        }
    }
});
scrollTimer.setInitialDelay(0);
scrollTimer.start();

The getFactor method is a conversion from linear to an easing function and would be implemented as one of these depending on how you want it to feel:

private double snap(double percent) {
    return 1;
}

private double linear(double percent) {
    return percent;
}

private double easeInCubic(double percent) {
    return Math.pow(percent, 3);
}

private double easeOutCubic(double percent) {
    return 1 - easeInCubic(1 - percent);
}

private double easeInOutCubic(double percent) {
    return percent < 0.5
            ? easeInCubic(percent * 2) / 2
            : easeInCubic(percent * -2 + 2) / -2 + 1;
}

This could probably be adapted to work within a component too so when the user scrolls it does something along these lines.

Or, if possible, you could use JavaFX which has much better support for animation than Swing.

like image 102
Rangi Keen Avatar answered Oct 08 '22 08:10

Rangi Keen