我试图将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();
}
}
}
}
答案 0 :(得分:2)
我不确定这是做什么的,但我发现至少有一件事:mousePressed
mouseReleased
和mouseExited
永远不会在你的班级ViewportDragScrollListener
中被调用,因为你不要转发事件。看完这篇文章后,他们没有使用这种技术,我认为这也可能是你问题的一部分。
考虑直接在正确的组件上添加鼠标侦听器,而不是像你那样转发事件。
编辑:
转发事件时,修改源,但该点仍在原始组件坐标中。请考虑使用以下代码创建新事件:
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, gridScrollPaneViewport);
答案 1 :(得分:2)
一种方法,使用SwingUtilities.convertMouseEvent(gamePanel,mouseEvent,viewport): (编辑:正如Guillaume Polet所说)
MouseAdapter convertMouseEventListener = new MouseAdapter() {
private void dispatchEvent(MouseEvent e) {
JComponent c = (JComponent)e.getComponent();
JComponent p = (JComponent)e.getComponent().getParent();
p.dispatchEvent(SwingUtilities.convertMouseEvent(c,e,p));
}
@Override public void mouseDragged(MouseEvent e) { dispatchEvent(e); }
@Override public void mouseClicked(MouseEvent e) { dispatchEvent(e); }
@Override public void mouseEntered(MouseEvent e) { dispatchEvent(e); }
@Override public void mouseExited(MouseEvent e) { dispatchEvent(e); }
@Override public void mousePressed(MouseEvent e) {
jTextArea.append(e.getPoint().toString() + "\n");
dispatchEvent(e);
}
@Override public void mouseReleased(MouseEvent e) { dispatchEvent(e); }
};
gameGridPanel.addMouseMotionListener(convertMouseEventListener);
gameGridPanel.addMouseListener(convertMouseEventListener);
另外,如果gameGridPanel有自己的MouseListeners,我sugest使用ComponentDragScrollListener而不是ViewportDragScrollListener:
ComponentDragScrollListener l = new ComponentDragScrollListener(gameGridPanel);
gameGridPanel.addMouseMotionListener(l);
gameGridPanel.addMouseListener(l);
gameGridPanel.addHierarchyListener(l);