これはトリックを行うようです:
class DocumentScroller extends JScrollPane implements ChangeListener {
Component view ;
JPanel bookPanel, bookTop ;
ScrollingDocumentListener listener ;
Dimension pageSize ;
public DocumentScroller ( Component view ) {
this.view = view ;
}
public DocumentScroller ( Component view,
int vsbPolicy, int hsbPolicy ) {
super( vsbPolicy, hsbPolicy ) ;
this.view = view ;
}
public void setViewportView ( Component view ) {
this.view = view ;
}
public void setPageCount ( int pagect ) {
if ( view == null )
return ;
pageSize = view.getPreferredSize() ;
Dimension bookSize = new Dimension( pageSize ) ;
bookSize.height *= pagect ;
bookPanel = new JPanel() ;
bookPanel.setLayout( new BorderLayout() ) ;
bookPanel.setPreferredSize( bookSize ) ;
bookPanel.add( bookTop = new JPanel(),
BorderLayout.NORTH ) ;
bookPanel.add( view, BorderLayout.CENTER ) ;
super.setViewportView( bookPanel ) ;
getViewport().addChangeListener( this ) ;
}
public void setUnitIncrement ( int unitIncrement ) {
getVerticalScrollBar().setUnitIncrement( unitIncrement ) ;
}
public void setValue ( int value ) {
getVerticalScrollBar().setValue( value ) ;
}
public void setScrollingDocumentListener (
ScrollingDocumentListener listener ) {
this.listener = listener ;
}
public void stateChanged ( ChangeEvent e ) {
try {
if ( e.getSource().getClass()
!= Class.forName(
"javax.swing.JViewport" ) )
return ;
}
catch ( Exception ex ) {
return ;
}
Rectangle rect = ( (JViewport) e.getSource()
).getViewRect() ;
int offset = rect.y %pageSize.height ;
int pageTop = rect.y -offset ;
int pos = offset *rect.height /pageSize.height ;
bookTop.setPreferredSize(
new Dimension( 0, pageTop +pos ) ) ;
bookPanel.doLayout() ;
if ( listener != null )
listener.setPage( pageTop /pageSize.height ) ;
}
}
interface ScrollingDocumentListener {
void setPage ( int pageno ) ;
}