0

I have a simple app that allows users to mark up a PDF document by dragging/dropping predefined widgets into a separate layer.

I am using a JScollPane. The viewport size is the equivalent of a single 8.5x11 page. When the VScrollBar is at the minimum position, the top of the page displays; at the maximum position, the bottom displays. I would like to override this behavior. The minimum position should display the top of the first page, and the maximum should display the bottom of the last page.

Among the dead ends I've hit: Replacing the ScrollBar built into the JScrollPane; Intercepting the AdjustmentEvent fired by the VScrollBar; and studying the ScrollDemo example. This seems like a straightforward feature, but I'm stuck at the beginning.

Any suggestions? Thanks!

4

2 回答 2

1

这似乎可以解决问题:

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 ) ;
    }
于 2012-04-12T04:07:21.203 回答
1

您是否希望能够同时显示第一页的下半部分和第二页的上半部分(并将元素从一个页面拖到另一个页面)?还是当时只有一个完整的页面?

首先,您需要一个仅显示所有页面并将其添加到 JScrollPane 的组件。您可能希望让它实现 Scrollable 接口来微调单元/块滚动。

第二,您可以在组件旁边显示一个(垂直)JScrollBar,并根据它的值更改显示的页面。在这种情况下,您使用的滚动条更像是一个滑块控件,并且您的页面组件并不是真正可滚动的(没有使用 JScrollPane)。

于 2012-04-11T15:17:58.670 回答