@@ -78,26 +78,26 @@ public static void main( String[] args ) {
7878 editorPaneLabel .setIcon ( new ColorIcon ( Color .orange .darker () ) );
7979 customLabel .setIcon ( new ColorIcon ( Color .pink ) );
8080
81- listScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "list vert" , Color .red .darker () ) );
82- listScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "list horz" , Color .red ) );
81+ listScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( listScrollPane , true , "list vert" , Color .red .darker () ) );
82+ listScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( listScrollPane , false , "list horz" , Color .red ) );
8383
84- treeScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "tree vert" , Color .blue .darker () ) );
85- treeScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "tree horz" , Color .blue ) );
84+ treeScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( treeScrollPane , true , "tree vert" , Color .blue .darker () ) );
85+ treeScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( treeScrollPane , false , "tree horz" , Color .blue ) );
8686
87- tableScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "table vert" , Color .green .darker () ) );
88- tableScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "table horz" , Color .green ) );
87+ tableScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( tableScrollPane , true , "table vert" , Color .green .darker () ) );
88+ tableScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( tableScrollPane , false , "table horz" , Color .green ) );
8989
90- textAreaScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "textArea vert" , Color .magenta .darker () ) );
91- textAreaScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "textArea horz" , Color .magenta ) );
90+ textAreaScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( textAreaScrollPane , true , "textArea vert" , Color .magenta .darker () ) );
91+ textAreaScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( textAreaScrollPane , false , "textArea horz" , Color .magenta ) );
9292
93- textPaneScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "textPane vert" , Color .cyan .darker () ) );
94- textPaneScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "textPane horz" , Color .cyan ) );
93+ textPaneScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( textPaneScrollPane , true , "textPane vert" , Color .cyan .darker () ) );
94+ textPaneScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( textPaneScrollPane , false , "textPane horz" , Color .cyan ) );
9595
96- editorPaneScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "editorPane vert" , Color .orange .darker () ) );
97- editorPaneScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "editorPane horz" , Color .orange ) );
96+ editorPaneScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( editorPaneScrollPane , true , "editorPane vert" , Color .orange .darker () ) );
97+ editorPaneScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( editorPaneScrollPane , false , "editorPane horz" , Color .orange ) );
9898
99- customScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "custom vert" , Color .pink ) );
100- customScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( "custom horz" , Color .pink .darker () ) );
99+ customScrollPane .getVerticalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( customScrollPane , true , "custom vert" , Color .pink ) );
100+ customScrollPane .getHorizontalScrollBar ().getModel ().addChangeListener ( new ScrollBarChangeHandler ( customScrollPane , false , "custom horz" , Color .pink .darker () ) );
101101
102102 ArrayList <String > items = new ArrayList <>();
103103 for ( char ch = '0' ; ch < 'z' ; ch ++ ) {
@@ -151,6 +151,13 @@ public Object getValueAt( int rowIndex, int columnIndex ) {
151151 }
152152 } );
153153
154+ // select some rows to better see smooth scrolling issues
155+ for ( int i = 5 ; i < items .size (); i += 10 ) {
156+ list .addSelectionInterval ( i , i );
157+ tree .addSelectionInterval ( i , i );
158+ table .addRowSelectionInterval ( i , i );
159+ }
160+
154161 // text components
155162 String text = items .stream ().collect ( Collectors .joining ( "\n " ) );
156163 textArea .setText ( text );
@@ -207,7 +214,7 @@ private void initComponents() {
207214 list = new JList <>();
208215 treeScrollPane = new FlatSmoothScrollingTest .DebugScrollPane ();
209216 tree = new JTree ();
210- tableScrollPane = new JScrollPane ();
217+ tableScrollPane = new FlatSmoothScrollingTest . DebugScrollPane ();
211218 table = new JTable ();
212219 textAreaLabel = new JLabel ();
213220 textPaneLabel = new JLabel ();
@@ -219,7 +226,7 @@ private void initComponents() {
219226 textPane = new JTextPane ();
220227 editorPaneScrollPane = new FlatSmoothScrollingTest .DebugScrollPane ();
221228 editorPane = new JEditorPane ();
222- customScrollPane = new JScrollPane ();
229+ customScrollPane = new FlatSmoothScrollingTest . DebugScrollPane ();
223230 button1 = new JButton ();
224231 scrollPane1 = new JScrollPane ();
225232 lineChartPanel = new FlatSmoothScrollingTest .LineChartPanel ();
@@ -382,7 +389,7 @@ private void initComponents() {
382389 private JList <String > list ;
383390 private FlatSmoothScrollingTest .DebugScrollPane treeScrollPane ;
384391 private JTree tree ;
385- private JScrollPane tableScrollPane ;
392+ private FlatSmoothScrollingTest . DebugScrollPane tableScrollPane ;
386393 private JTable table ;
387394 private JLabel textAreaLabel ;
388395 private JLabel textPaneLabel ;
@@ -394,7 +401,7 @@ private void initComponents() {
394401 private JTextPane textPane ;
395402 private FlatSmoothScrollingTest .DebugScrollPane editorPaneScrollPane ;
396403 private JEditorPane editorPane ;
397- private JScrollPane customScrollPane ;
404+ private FlatSmoothScrollingTest . DebugScrollPane customScrollPane ;
398405 private JButton button1 ;
399406 private JScrollPane scrollPane1 ;
400407 private FlatSmoothScrollingTest .LineChartPanel lineChartPanel ;
@@ -413,39 +420,52 @@ private class ScrollBarChangeHandler
413420 private int count ;
414421 private long lastTime ;
415422
416- ScrollBarChangeHandler ( String name , Color chartColor ) {
423+ ScrollBarChangeHandler ( DebugScrollPane scrollPane , boolean vertical , String name , Color chartColor ) {
417424 this .name = name ;
418425 this .chartColor = chartColor ;
426+
427+ // add change listener to viewport that is invoked from JViewport.setViewPosition()
428+ scrollPane .getViewport ().addChangeListener ( e -> {
429+ // add dot to chart if blit scroll mode is disabled
430+ if ( vertical == scrollPane .lastScrollingWasVertical &&
431+ scrollPane .getViewport ().getScrollMode () != JViewport .BLIT_SCROLL_MODE )
432+ {
433+ JScrollBar sb = vertical ? scrollPane .getVerticalScrollBar () : scrollPane .getHorizontalScrollBar ();
434+ lineChartPanel .addValue ( getChartValue ( sb .getModel () ), true , chartColor );
435+ }
436+ } );
419437 }
420438
421439 @ Override
422440 public void stateChanged ( ChangeEvent e ) {
423441 DefaultBoundedRangeModel m = (DefaultBoundedRangeModel ) e .getSource ();
424- int value = m .getValue ();
425- boolean valueIsAdjusting = m .getValueIsAdjusting ();
426442
427- if ( chartColor != null ) {
428- double chartValue = (double ) (value - m .getMinimum ()) / (double ) (m .getMaximum () - m .getExtent ());
429- lineChartPanel .addValue ( chartValue , chartColor );
430- }
443+ lineChartPanel .addValue ( getChartValue ( m ), chartColor );
431444
432445 long t = System .nanoTime () / 1000000 ;
433446
434447 System .out .printf ( "%s (%d): %4d %3d ms %b%n" ,
435448 name , ++count ,
436- value ,
449+ m . getValue () ,
437450 t - lastTime ,
438- valueIsAdjusting );
451+ m . getValueIsAdjusting () );
439452
440453 lastTime = t ;
441454 }
455+
456+ private double getChartValue ( BoundedRangeModel m ) {
457+ int value = m .getValue ();
458+ return (double ) (value - m .getMinimum ()) / (double ) (m .getMaximum () - m .getExtent ());
459+ }
442460 }
443461
444462 //---- class DebugViewport ------------------------------------------------
445463
446464 private static class DebugScrollPane
447465 extends JScrollPane
448466 {
467+ boolean lastScrollingWasVertical ;
468+
449469 @ Override
450470 protected JViewport createViewport () {
451471 return new JViewport () {
@@ -455,6 +475,23 @@ public Point getViewPosition() {
455475// System.out.println( " viewPosition " + viewPosition.x + "," + viewPosition.y );
456476 return viewPosition ;
457477 }
478+
479+ @ Override
480+ public void setViewPosition ( Point p ) {
481+ // remember whether scrolling vertically or horizontally
482+ Component view = getView ();
483+ if ( view != null ) {
484+ int oldY = (view instanceof JComponent )
485+ ? ((JComponent ) view ).getY ()
486+ : view .getBounds ().y ;
487+
488+ int newY = -p .y ;
489+ lastScrollingWasVertical = (oldY != newY );
490+ } else
491+ lastScrollingWasVertical = true ;
492+
493+ super .setViewPosition ( p );
494+ }
458495 };
459496 }
460497 }
0 commit comments