ScrollBar: fixed temporary painting at wrong location during smooth scrolling when using mouse-wheel or scroll bar

(still occurs when scrolling by moving selection via keyboard)

many thanks to @Chrriis for the idea to temporary disable blitting mode on viewport
This commit is contained in:
Karl Tauber
2023-06-04 19:40:18 +02:00
parent 29f6c5fae9
commit cf70cfb50c
4 changed files with 97 additions and 35 deletions

View File

@@ -34,6 +34,7 @@ import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
@@ -480,12 +481,14 @@ public class FlatScrollBarUI
// remember current scrollbar value so that we can start scroll animation from there
int oldValue = scrollbar.getValue();
// if invoked while animation is running, calculation of new value
// should start at the previous target value
if( targetValue != Integer.MIN_VALUE )
scrollbar.setValue( targetValue );
runWithoutBlitting( scrollbar.getParent(), () ->{
// if invoked while animation is running, calculation of new value
// should start at the previous target value
if( targetValue != Integer.MIN_VALUE )
scrollbar.setValue( targetValue );
r.run();
r.run();
} );
// do not use animation if started dragging thumb
if( isDragging ) {
@@ -507,6 +510,26 @@ public class FlatScrollBarUI
inRunAndSetValueAnimated = false;
}
private void runWithoutBlitting( Container scrollPane, Runnable r ) {
// prevent the viewport to immediately repaint using blitting
JViewport viewport = null;
int oldScrollMode = 0;
if( scrollPane instanceof JScrollPane ) {
viewport = ((JScrollPane) scrollPane).getViewport();
if( viewport != null ) {
oldScrollMode = viewport.getScrollMode();
viewport.setScrollMode( JViewport.BACKINGSTORE_SCROLL_MODE );
}
}
try {
r.run();
} finally {
if( viewport != null )
viewport.setScrollMode( oldScrollMode );
}
}
private boolean inRunAndSetValueAnimated;
private Animator animator;
private int startValue = Integer.MIN_VALUE;

View File

@@ -455,6 +455,8 @@ public class FlatScrollPaneUI
@Override
protected void syncScrollPaneWithViewport() {
// if the viewport has been scrolled by using JComponent.scrollRectToVisible()
// (e.g. by moving selection), then it is necessary to update the scroll bar values
if( isSmoothScrollingEnabled() ) {
runAndSyncScrollBarValueAnimated( scrollpane.getVerticalScrollBar(), 0, () -> {
runAndSyncScrollBarValueAnimated( scrollpane.getHorizontalScrollBar(), 1, () -> {