Pentomino游戏Polygon图形拖拽异常问题求助
Pentomino游戏棋子拖拽边界不匹配问题排查与修复
问题描述
开发Pentomino游戏时遇到棋子移动异常:图形虽能拖动,但每次拖拽后Polygon的边界坐标与实际图形边界不匹配,最终导致无法继续拖拽。
错误原因分析
针对你提供的代码,问题集中在mousePressed和mouseDragged方法:
- 未记录选中的图形:每次拖拽都遍历所有
Polygon,且用初始鼠标位置判断是否包含在图形边界内,拖拽过程中图形位置改变后,该判断会失效,无法正确识别要移动的图形。 - 鼠标偏移量处理错误:仅记录鼠标按下时的坐标,未计算鼠标相对于图形边界的偏移,导致拖拽时图形移动的基准点错误,边界与实际位置逐渐脱节。
- 无效的循环repaint:修改每个顶点后都调用
repaint(),既浪费资源又可能导致绘制异常。
修复方案
- 添加变量记录当前选中的Polygon和鼠标相对于图形的偏移量,避免重复遍历和错误判断。
- 在
mousePressed时,准确计算鼠标与图形边界的偏移,确保拖拽时图形跟随鼠标位置移动。 - 在
mouseDragged时,仅对选中的图形进行操作,更新所有顶点坐标后统一调用repaint()。
修复后的完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; public class MyPanel extends JFrame implements MouseListener, MouseMotionListener { JPanel mainPane; ArrayList<Polygon> polygons = new ArrayList<>(); // 新增变量:记录选中的图形和鼠标偏移量 Polygon selectedPolygon = null; Point offset; Polygon fig1 = new Polygon(new int[]{50, 90, 90, 50}, new int[]{50, 50, 200, 200}, 4); Polygon fig2 = new Polygon(new int[]{170, 250, 250, 210, 210, 170, 170, 130, 130, 170}, new int[]{80, 80, 120, 120, 200, 200, 160, 160, 120, 120}, 10); Polygon fig3 = new Polygon(new int[]{370, 410, 410, 330, 330, 370}, new int[]{90, 90, 200, 200, 160, 160}, 6); MyPanel(){ polygons.add(fig1); polygons.add(fig2); polygons.add(fig3); mainPane = new JPanel(){ @Override public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; for(Shape fig: polygons){ g2.setColor(Color.BLUE); g2.fill(fig); } } }; getContentPane().add(mainPane); mainPane.setLayout(null); setVisible(true); setSize(1000, 600); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); mainPane.addMouseListener(this); mainPane.addMouseMotionListener(this); } @Override public void mousePressed(MouseEvent e) { selectedPolygon = null; for(Polygon polygon: polygons) { if (polygon.contains(e.getPoint())) { selectedPolygon = polygon; // 计算鼠标相对于图形左上角的偏移量 Rectangle bounds = polygon.getBounds(); offset = new Point(e.getX() - bounds.x, e.getY() - bounds.y); break; } } } @Override public void mouseClicked(MouseEvent e){} @Override public void mouseReleased(MouseEvent e){ selectedPolygon = null; // 释放鼠标后取消选中 } @Override public void mouseEntered(MouseEvent e){} @Override public void mouseExited(MouseEvent e){} @Override public void mouseDragged(MouseEvent e) { if(selectedPolygon != null) { // 计算图形需要移动到的目标位置 int targetX = e.getX() - offset.x; int targetY = e.getY() - offset.y; // 获取图形当前的边界 Rectangle currentBounds = selectedPolygon.getBounds(); // 计算移动的差值 int dx = targetX - currentBounds.x; int dy = targetY - currentBounds.y; // 更新所有顶点坐标 for (int i = 0; i < selectedPolygon.npoints; i++) { selectedPolygon.xpoints[i] += dx; selectedPolygon.ypoints[i] += dy; } // 统一重绘 repaint(); } } @Override public void mouseMoved(MouseEvent e){} public static void main(String[] args) { new MyPanel(); } }
关键修复点说明
- 选中状态管理:用
selectedPolygon变量记录当前拖拽的图形,避免每次遍历所有图形,提升效率和准确性。 - 偏移量计算:在
mousePressed时计算鼠标与图形边界的相对位置,确保拖拽过程中图形始终跟随鼠标点击的位置移动,不会出现偏移。 - 批量更新与重绘:修改完所有顶点坐标后再调用
repaint(),减少绘制次数,避免界面闪烁。
内容的提问来源于stack exchange,提问作者Ssalmor
相关产品推荐
相关产品推荐

