Java/Swing JViewport 鼠标拖动时跳转

标签 java swing mouseevent jscrollpane

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

gameGrid 标签实际上是一个带有单击事件的单独类,这就是为什么我让鼠标监听器尝试调用父 mouseListeners(以前网格 mouseListeners 覆盖了可滚动视口(viewport) 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);

关于Java/Swing JViewport 鼠标拖动时跳转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10813327/

相关文章:

java - 客户端无法向服务器 Java 套接字发送消息

java - 分层存储常量的最佳实践

java - 在 JFrame 中显示 JPanel 的内容

Java模拟时钟

java - 当成员加入 Hazelcast 集群时,集群停止写入操作

Java泛型编程: Determining if class extends another

javascript - 鼠标悬停时无限旋钮

c++ - 无法在某些小部件上触发鼠标事件

java - 右键单击对象后如何使用 JOptionPane()

java - AsyncTask 得到一个错误的字符串参数