我试图将http://java-swing-tips.blogspot.co.uk/2008/06/mouse-drag-auto-scrolling.html集成到我的程序中,但是似乎行为不当,我不确定发生了什么。

gameGrid标签实际上是带有单击事件的单独类,这就是为什么我让鼠标侦听器尝试调用父mouseListeners(以前,网格mouseListeners覆盖了可滚动视口mouseListeners,因此它不会拖动),但是JPanel一些形状显示相同的行为。

package uk.co.mhayward.games.factions;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.Polygon;
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 java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;

public class WhyYouJump extends JFrame {

    public static void main(String[] args) {
        new WhyYouJump();
    }

    private static final long serialVersionUID = 3697837493691218641L;

    private final JPanel gameGridPanel;

    private final JScrollPane gridScrollPane;

    private final JViewport gridScrollPaneViewport;

    private final JTextArea jTextArea = new JTextArea();

    public WhyYouJump() throws HeadlessException {
        super();

        gameGridPanel = new JPanel() {
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                Graphics2D g2d = (Graphics2D) g;

                Polygon shape1 = new Polygon();
                Polygon shape2 = new Polygon();
                Polygon shape3 = new Polygon();

                for (int i = 0; i < 6; i++) {
                    shape1.addPoint((int) (200 + 50 * Math.cos(i * 2 * Math.PI / 6)),
                            (int) (200 + 50 * Math.sin(i * 2 * Math.PI / 6)));
                    shape2.addPoint((int) (400 + 50 * Math.cos(i * 2 * Math.PI / 6)),
                            (int) (200 + 50 * Math.sin(i * 2 * Math.PI / 6)));
                    shape3.addPoint((int) (100 + 50 * Math.cos(i * 2 * Math.PI / 6)),
                            (int) (100 + 50 * Math.sin(i * 2 * Math.PI / 6)));
                }

                g2d.setStroke(new BasicStroke(3));
                g2d.setPaint(Color.WHITE);
                g2d.fill(shape1);
                g2d.fill(shape2);
                g2d.fill(shape3);
                g2d.setPaint(Color.BLACK);
                g2d.draw(shape1);
                g2d.draw(shape2);
                g2d.draw(shape3);
            }
        };

        gameGridPanel.setPreferredSize(new Dimension(1440, 900));
        gameGridPanel.setSize(new Dimension(1440, 900));

        gridScrollPane = new JScrollPane(gameGridPanel);

        gameGridPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                for (MouseListener l : gameGridPanel.getParent().getMouseListeners()) {
                    e.setSource(gridScrollPaneViewport);
                    l.mousePressed(e);
                }
                jTextArea.append(e.getPoint().toString() + "\n");
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                for (MouseListener l : gameGridPanel.getParent().getMouseListeners()) {
                    e.setSource(gridScrollPaneViewport);
                    l.mouseReleased(e);
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                for (MouseListener l : gameGridPanel.getParent().getMouseListeners()) {
                    e.setSource(gridScrollPaneViewport);
                    l.mouseExited(e);
                }
            }
        });

        gameGridPanel.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                for (MouseMotionListener l : gameGridPanel.getParent().getMouseMotionListeners()) {
                    e.setSource(gridScrollPaneViewport);
                    l.mouseDragged(e);
                }
            }
        });

        gameGridPanel.addHierarchyListener(new HierarchyListener() {

            public void hierarchyChanged(HierarchyEvent e) {
                for (HierarchyListener l : gameGridPanel.getParent().getHierarchyListeners()) {
                    e.setSource(gridScrollPaneViewport);
                    l.hierarchyChanged(e);
                }
            }
        });

        this.setLayout(new BorderLayout());
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        gridScrollPane.setPreferredSize(new Dimension(500, 300));
        gridScrollPane.getVerticalScrollBar().setUnitIncrement(16);

        ViewportDragScrollListener l = new ViewportDragScrollListener(gameGridPanel, false);
        gridScrollPaneViewport = gridScrollPane.getViewport();
        gridScrollPaneViewport.addMouseMotionListener(l);
        gridScrollPaneViewport.addMouseListener(l);
        gridScrollPaneViewport.addHierarchyListener(l);

        this.add("Center", gridScrollPane);

        JScrollPane textScrollPane = new JScrollPane(jTextArea);
        textScrollPane.setPreferredSize(new Dimension(140, 180));
        this.add("South", textScrollPane);

        this.pack();
        this.setLocation(100, 100);
        this.setVisible(true);
    }

    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); //label.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); //label.setCursor(dc);
            if (autoScroll) {
                scroller.start();
            }
        }

        @Override
        public void mouseExited(MouseEvent e) {
            ((JComponent) e.getSource()).setCursor(dc); //label.setCursor(dc);
            move.setLocation(0, 0);
            if (autoScroll) {
                scroller.stop();
            }
        }
    }
}

最佳答案

我不确定这到底在做什么,但我至少可以发现一件事:mousePressed mouseReleasedmouseExited不会在您的类ViewportDragScrollListener中被调用,因为您不转发事件。看完文章后,他们没有使用这种技术,我认为这也可能是您遇到的问题之一。

考虑将鼠标侦听器直接添加到正确的组件上,而不是像您一样转发事件。

编辑:

转发事件时,可以修改源,但该点仍在原始组件坐标中。考虑使用以下代码创建一个新事件:

e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, gridScrollPaneViewport);

10-04 17:29