1

If I make a JScrollPane and add a JPanel in it, I would like to be able to scroll the pane around by clicking a dragging inside the JScollPane.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Chris Smith
  • 2,928
  • 4
  • 27
  • 59
  • Have you tried anything yet? Is there a problem with what you tried already? – The Guy with The Hat Apr 04 '14 at 21:34
  • I don't know how to do it simply. I don't know where to start. – Chris Smith Apr 04 '14 at 21:35
  • There are a lot of good tutorials online. Google is your friend! – The Guy with The Hat Apr 04 '14 at 21:36
  • Is there a site you have? I can't seem to find anything on Google. I could not figure this out: http://stackoverflow.com/questions/16378109/java-swing-scrolling-by-dragging-the-mouse – Chris Smith Apr 04 '14 at 21:38
  • [How to write a MouseMotionListener](http://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html) would be a good start and [JComponent#scrollRectToVisible](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#scrollRectToVisible(java.awt.Rectangle)) would also be of interest... – MadProgrammer Apr 04 '14 at 21:39
  • So I make a MouseMotionListener, then how do I compare two mouseDrags? Can I say, e.draggedTo()? – Chris Smith Apr 04 '14 at 21:54
  • Try this related [example](http://stackoverflow.com/a/7203419/230513). – trashgod Apr 04 '14 at 22:02
  • You would need to know the original position of the current view, the click point (so you can calculate an offset) and then simply add this offset to the current drag point... – MadProgrammer Apr 04 '14 at 22:44
  • I made a custom class for this and it works great! Just have to wait 8 hours till I can answer my own question because I have below 10 reputation. – Chris Smith Apr 04 '14 at 23:38
  • Added the custom class as an answer. – Chris Smith Apr 05 '14 at 20:39

1 Answers1

1

I made a custom JScrollPane, use it as you would a normal JScrollPane.

import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JViewport;

public class DragScrollPane extends JScrollPane {
    private static final long serialVersionUID = 1L;

    public DragScrollPane(JComponent objectToMove) {
        super(objectToMove);
        ViewportDragScrollListener l = new ViewportDragScrollListener(
                objectToMove, false);
        JViewport gridScrollPaneViewport = getViewport();
        gridScrollPaneViewport.addMouseMotionListener(l);
        gridScrollPaneViewport.addMouseListener(l);
        gridScrollPaneViewport.addHierarchyListener(l);
    }

    class ViewportDragScrollListener extends MouseAdapter implements
            HierarchyListener {
        private static final int SPEED = 4;
        private static final int DELAY = 10;
        private final Cursor dc;
        private final Cursor hc = Cursor
                .getPredefinedCursor(Cursor.HAND_CURSOR);
        private final javax.swing.Timer scroller;
        private final JComponent label;
        private final Point startPt = new Point();
        private final Point move = new Point();
        private boolean autoScroll = false;

        public ViewportDragScrollListener(JComponent comp, boolean autoScroll) {
            this.label = comp;
            this.autoScroll = autoScroll;
            this.dc = comp.getCursor();
            this.scroller = new javax.swing.Timer(DELAY, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    JViewport vport = (JViewport) label.getParent();
                    Point vp = vport.getViewPosition();
                    vp.translate(move.x, move.y);
                    label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
                }
            });
        }

        public void hierarchyChanged(HierarchyEvent e) {
            JComponent c = (JComponent) e.getSource();
            if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
                    && !c.isDisplayable() && autoScroll) {
                scroller.stop();
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            JViewport vport = (JViewport) e.getSource();
            Point pt = e.getPoint();
            int dx = startPt.x - pt.x;
            int dy = startPt.y - pt.y;
            Point vp = vport.getViewPosition();
            vp.translate(dx, dy);
            label.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
            move.setLocation(SPEED * dx, SPEED * dy);
            startPt.setLocation(pt);
        }

        @Override
        public void mousePressed(MouseEvent e) {
            ((JComponent) e.getSource()).setCursor(hc);
            startPt.setLocation(e.getPoint());
            move.setLocation(0, 0);
            if (autoScroll) {
                scroller.stop();
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            ((JComponent) e.getSource()).setCursor(dc);
            if (autoScroll) {
                scroller.start();
            }
        }

        @Override
        public void mouseExited(MouseEvent e) {
            ((JComponent) e.getSource()).setCursor(dc);
            move.setLocation(0, 0);
            if (autoScroll) {
                scroller.stop();
            }
        }
    }
}
Chris Smith
  • 2,928
  • 4
  • 27
  • 59