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
相关产品推荐
相关产品推荐

