You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pentomino游戏Polygon图形拖拽异常问题求助

Pentomino游戏棋子拖拽边界不匹配问题排查与修复

问题描述

开发Pentomino游戏时遇到棋子移动异常:图形虽能拖动,但每次拖拽后Polygon的边界坐标与实际图形边界不匹配,最终导致无法继续拖拽。

错误原因分析

针对你提供的代码,问题集中在mousePressed和mouseDragged方法:

  1. 未记录选中的图形:每次拖拽都遍历所有Polygon,且用初始鼠标位置判断是否包含在图形边界内,拖拽过程中图形位置改变后,该判断会失效,无法正确识别要移动的图形。
  2. 鼠标偏移量处理错误:仅记录鼠标按下时的坐标,未计算鼠标相对于图形边界的偏移,导致拖拽时图形移动的基准点错误,边界与实际位置逐渐脱节。
  3. 无效的循环repaint:修改每个顶点后都调用repaint(),既浪费资源又可能导致绘制异常。

修复方案

  1. 添加变量记录当前选中的Polygon和鼠标相对于图形的偏移量,避免重复遍历和错误判断。
  2. 在mousePressed时,准确计算鼠标与图形边界的偏移,确保拖拽时图形跟随鼠标位置移动。
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:00:52