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

Java Swing五连块图形拖拽无实时刷新问题求助

Java Swing五连块拖拽无实时更新问题解决

问题描述

开发基于Java Swing的五连块(Pentomino)程序时,拖拽图形时图形实际位置已改变,但无实时移动动画效果,需将程序窗口最小化或最大化后,才能显示移动后的图形。

原代码

PentominoShape类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;

public class PentominoShape extends JFrame implements MouseListener, MouseMotionListener {
    JPanel shapePane;
    Container contentPane;
    private Polygon currPolygon;
    private int x, y;
    ArrayList<Polygon> polygons = new ArrayList<Polygon>();
    JFrame frame;
    public PentominoShape(JFrame frame){
        this.frame = frame;
        initShape();
    }
    private void initShape() {
        Polygon fig1 = new Polygon(new int[]{10, 50, 50, 10}, new int[]{10, 10, 200, 200}, 4);
        Polygon fig2 = new Polygon(new int[]{130, 210, 210, 170, 170, 130, 130, 90, 90, 130}, new int[]{80, 80, 120, 120, 200, 200, 160, 160, 120, 120}, 10);
        Polygon fig3 = new Polygon(new int[]{290, 330, 330, 250, 250, 290}, new int[]{50, 50, 200, 200, 160, 160}, 6);
        Polygon fig4 = new Polygon(new int[]{10, 90, 90, 50, 50, 10}, new int[]{280, 280, 400, 400, 360, 360}, 6);
        Polygon fig5 = new Polygon(new int[]{170, 210, 210, 170, 170, 130, 130, 170}, new int[]{240, 240, 360, 360, 400, 400, 320, 320}, 8);
        Polygon fig6 = new Polygon(new int[]{250, 370, 370, 330, 330, 290, 290, 250}, new int[]{280, 280, 320, 320, 400, 400, 320, 320}, 8);
        Polygon fig7 = new Polygon(new int[]{10, 50, 50, 90, 90, 130, 130, 10}, new int[]{480, 480, 520, 520, 480, 480, 560, 560}, 8);
        Polygon fig8 = new Polygon(new int[]{170, 250, 250, 290, 290, 170}, new int[]{520, 520, 440, 440, 560, 560}, 6);
        Polygon fig9 = new Polygon(new int[]{330, 370, 370, 410, 410, 450, 450, 410, 410, 330}, new int[]{520, 520, 480, 480, 440, 440, 520, 520, 560, 560}, 10);
        Polygon fig10 = new Polygon(new int[]{10, 50, 50, 90, 90, 130, 130, 90, 90, 50, 50, 10}, new int[]{680, 680, 640, 640, 680, 680, 720, 720, 760, 760, 720, 720}, 12);
        Polygon fig11 = new Polygon(new int[]{170, 210, 210, 250, 250, 210, 210, 170}, new int[]{640, 640, 600, 600, 760, 760, 680, 680}, 8);
        Polygon fig12 = new Polygon(new int[]{330, 410, 410, 370, 370, 290, 290, 330}, new int[]{640, 640, 680, 680, 760, 760, 720, 720}, 8);

        polygons.add(fig1);
        polygons.add(fig2);
        polygons.add(fig3);
        polygons.add(fig4);
        polygons.add(fig5);
        polygons.add(fig6);
        polygons.add(fig7);
        polygons.add(fig8);
        polygons.add(fig9);
        polygons.add(fig10);
        polygons.add(fig11);
        polygons.add(fig12);

        Color[] c = new Color[12];
        c[0] = new Color(25, 165, 25);
        c[1] = new Color(255, 165, 25);
        c[2] = new Color(255, 50, 50);
        c[3] = new Color(150, 45, 90);
        c[4] = new Color(25, 165, 150);
        c[5] = new Color(25, 165, 255);
        c[6] = new Color(255, 40, 190);
        c[7] = new Color(180, 90, 60);
        c[8] = new Color(90, 80, 70);
        c[9] = new Color(70, 80, 90);
        c[10] = new Color(150, 30, 20);
        c[11] = new Color(80, 80, 80);

        shapePane = new JPanel(){
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;

                g2.setColor(c[0]); g2.fill(fig1);
                g2.setColor(c[1]); g2.fill(fig2);
                g2.setColor(c[2]); g2.fill(fig3);
                g2.setColor(c[3]); g2.fill(fig4);
                g2.setColor(c[4]); g2.fill(fig5);
                g2.setColor(c[5]); g2.fill(fig6);
                g2.setColor(c[6]); g2.fill(fig7);
                g2.setColor(c[7]); g2.fill(fig8);
                g2.setColor(c[8]); g2.fill(fig9);
                g2.setColor(c[9]); g2.fill(fig10);
                g2.setColor(c[10]); g2.fill(fig11);
                g2.setColor(c[11]); g2.fill(fig12);
            }
        };

        frame.add(shapePane);

        shapePane.addMouseListener(this);
        shapePane.addMouseMotionListener(this);
    }
    public void mousePressed(MouseEvent e) {
        for(Polygon polygon: polygons) {
            if (polygon.contains(e.getPoint())) {
                System.out.println("Pressed");
                currPolygon = polygon;
                x = e.getX();
                y = e.getY();
            }
        }
    }
    public void mouseDragged(MouseEvent e) {
        try {
            if (currPolygon.contains(x, y)) {
                System.out.println("Dragged");
                int dx = e.getX() - x;
                int dy = e.getY() - y;
                currPolygon.translate(dx, dy);
                x += dx;
                y += dy;
                repaint();
            }
        }catch (NullPointerException ex){

        }
    }
    public void mouseReleased(MouseEvent e){
        currPolygon = null;
    }
    public void mouseClicked(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mouseMoved(MouseEvent e){}

}

Pentomino类

import javax.swing.*;

public class Pentomino extends JFrame {
    JFrame frame;
    PentominoShape shape;
    PentominoPanel panel;
    public Pentomino(){
        initUI();
    }

    private void initUI(){
        frame = new JFrame("Пентамино");
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setSize(1500, 900);
        setResizable(false);

        shape = new PentominoShape(frame);
        panel = new PentominoPanel(frame);

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Pentomino game = new Pentomino();
    }
}

解决方案

1. 修复绘制数据不一致问题

paintComponent方法原本直接使用初始化时的局部变量fig1-fig12,但拖拽修改的是polygons列表中的对象,导致绘制内容未更新。修改为遍历polygons列表绘制:

shapePane = new JPanel(){
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        Color[] c = new Color[12];
        c[0] = new Color(25, 165, 25);
        c[1] = new Color(255, 165, 25);
        c[2] = new Color(255, 50, 50);
        c[3] = new Color(150, 45, 90);
        c[4] = new Color(25, 165, 150);
        c[5] = new Color(25, 165, 255);
        c[6] = new Color(255, 40, 190);
        c[7] = new Color(180, 90, 60);
        c[8] = new Color(90, 80, 70);
        c[9] = new Color(70, 80, 90);
        c[10] = new Color(150, 30, 20);
        c[11] = new Color(80, 80, 80);
        
        for(int i=0; i<polygons.size(); i++){
            g2.setColor(c[i]);
            g2.fill(polygons.get(i));
        }
    }
};

2. 修正重绘调用对象

原代码中调用repaint()是触发PentominoShape类的重绘,但实际负责绘制的是shapePane面板,需要调用shapePane.repaint()才能实时刷新:

public void mouseDragged(MouseEvent e) {
    try {
        if (currPolygon != null) {
            System.out.println("Dragged");
            int dx = e.getX() - x;
            int dy = e.getY() - y;
            currPolygon.translate(dx, dy);
            x += dx;
            y += dy;
            shapePane.repaint(); // 触发面板重绘
        }
    }catch (NullPointerException ex){
        ex.printStackTrace(); // 保留异常信息用于调试
    }
}

同时替换了原有的currPolygon.contains(x,y)判断,因为图形平移后初始坐标可能不再处于图形内,导致拖拽中断,直接判断currPolygon != null更可靠。

3. 移除冗余继承

PentominoShape继承JFrame但并未作为窗口使用,改为普通类:

public class PentominoShape implements MouseListener, MouseMotionListener {
    // 其余代码不变
}

4. 简化主类代码

主类Pentomino本身继承JFrame,无需额外创建frame对象,同时使用SwingUtilities.invokeLater确保Swing组件在事件调度线程中初始化:

import javax.swing.*;

public class Pentomino extends JFrame {
    PentominoShape shape;
    // PentominoPanel panel; // 未实现可暂时注释
    public Pentomino(){
        initUI();
    }

    private void initUI(){
        setTitle("Пентамино");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(1500, 900);
        setResizable(false);

        shape = new PentominoShape(this);
        // panel = new PentominoPanel(this);
        add(shape); // 直接添加到当前窗口

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Pentomino());
    }
}

内容的提问来源于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 16:10:29