我试图将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
mouseReleased
和mouseExited
不会在您的类ViewportDragScrollListener
中被调用,因为您不转发事件。看完文章后,他们没有使用这种技术,我认为这也可能是您遇到的问题之一。
考虑将鼠标侦听器直接添加到正确的组件上,而不是像您一样转发事件。
编辑:
转发事件时,可以修改源,但该点仍在原始组件坐标中。考虑使用以下代码创建一个新事件:
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, gridScrollPaneViewport);