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

为何用while循环绘制国际象棋棋盘在台式机显示后消失,笔记本正常?

问题:国际象棋棋盘绘制后瞬间消失

我用while循环绘制国际象棋棋盘,但棋盘方块显示一秒后就消失了。这段代码在笔记本上运行完全正常,但放到台式机上就出现问题——笔记本上棋盘能正常显示,台式机上棋盘只闪一下就没了。

面板代码

package chess;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JPanel;

public class ChessBoard extends JPanel{

    public int tileSize = 90;
    public int cols = 8;
    public int rows = 8;
    public int maxCols = cols * tileSize;
    public int maxRows = rows * tileSize;
    TileManager tileM = new TileManager(this);
    
    ChessBoard(){
        
        this.setPreferredSize(new Dimension(maxCols, maxRows));
        this.setBackground(Color.black);
        this.setDoubleBuffered(true); 
        this.setFocusable(true); 
        
    }
    
    public void paintComponent(Graphics g) {
        
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        tileM.drawTiles(g2);
        
    }

}

绘制逻辑代码

package chess;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.imageio.ImageIO;

public class TileManager {

    ChessBoard cb;
    public static int [] types = new int[10];
    private static int rows = 0;
    private static int cols = 0;
    private boolean c = true;
    String [] alpha = {"a", "b", "c", "d", "e", "f", "g", "h"};
    String [] num = {"8", "7", "6", "5", "4", "3", "2", "1"};
    
    TileManager(ChessBoard cb){
        
        this.cb = cb;
        
    }
    
    public void drawTiles(Graphics g) {
        
        Graphics2D g2 = (Graphics2D)g;
        
        while (rows < cb.rows && cols < cb.cols) {
            
            if (c)  g.setColor(Color.white);
            if (!c) g.setColor(Color.black);
            
            g2.setFont(new Font("Comic Sans", Font.BOLD, 20));
            g2.fillRect(cols * cb.tileSize, rows * cb.tileSize, cb.tileSize, cb.tileSize);
            g2.setColor(Color.green);
            g2.drawString(alpha[cols], 5 + cols * cb.tileSize, 20 + rows * cb.tileSize);
            g2.drawString(num[rows], 75 + cols * cb.tileSize, 85 + rows * cb.tileSize);
            
            c = !c;
            cols++;

            if (cols == 8) {
                
                c = !c;
                cols = 0;
                rows++;
                
            }
            
        }
        
    }
    
}

问题原因

核心问题出在TileManager里的rows和cols被声明为static:

  • 第一次调用drawTiles时,循环会把rows和cols递增到8,满足循环终止条件。
  • Swing的paintComponent方法会被系统多次调用(比如窗口移动、最小化恢复、其他窗口遮挡后恢复等),当第二次调用drawTiles时,rows和cols还是8,循环条件rows < cb.rows && cols < cb.cols不成立,所以不会绘制任何内容,看起来就是棋盘消失了。
  • 笔记本可能刚好没触发额外的重绘,所以第一次绘制后没被刷新,而台式机触发了重绘,就出现了消失的问题。

修复方案

把rows和cols的static修饰符去掉,并且每次调用drawTiles时初始化这两个变量为0,确保每次重绘都能重新执行循环绘制棋盘:

修改后的TileManager核心代码:

public class TileManager {

    ChessBoard cb;
    public static int [] types = new int[10];
    // 去掉static修饰符
    private int rows = 0;
    private int cols = 0;
    private boolean c = true;
    String [] alpha = {"a", "b", "c", "d", "e", "f", "g", "h"};
    String [] num = {"8", "7", "6", "5", "4", "3", "2", "1"};
    
    TileManager(ChessBoard cb){
        this.cb = cb;
    }
    
    public void drawTiles(Graphics g) {
        
        Graphics2D g2 = (Graphics2D)g;
        // 每次绘制前重置变量
        rows = 0;
        cols = 0;
        c = true;
        
        while (rows < cb.rows && cols < cb.cols) {
            
            g.setColor(c ? Color.white : Color.black);
            
            g2.setFont(new Font("Comic Sans", Font.BOLD, 20));
            g2.fillRect(cols * cb.tileSize, rows * cb.tileSize, cb.tileSize, cb.tileSize);
            g2.setColor(Color.green);
            g2.drawString(alpha[cols], 5 + cols * cb.tileSize, 20 + rows * cb.tileSize);
            g2.drawString(num[rows], 75 + cols * cb.tileSize, 85 + rows * cb.tileSize);
            
            c = !c;
            cols++;

            if (cols == 8) {
                c = !c;
                cols = 0;
                rows++;
            }
        }
    }
}

另外,也可以把while循环换成for循环,逻辑会更清晰,避免变量重置的问题:

public void drawTiles(Graphics g) {
    
    Graphics2D g2 = (Graphics2D)g;
    g2.setFont(new Font("Comic Sans", Font.BOLD, 20));
    
    for(int row = 0; row < cb.rows; row++){
        boolean isWhite = row % 2 == 0;
        for(int col = 0; col < cb.cols; col++){
            g.setColor(isWhite ? Color.white : Color.black);
            g2.fillRect(col * cb.tileSize, row * cb.tileSize, cb.tileSize, cb.tileSize);
            g2.setColor(Color.green);
            g2.drawString(alpha[col], 5 + col * cb.tileSize, 20 + row * cb.tileSize);
            g2.drawString(num[row], 75 + col * cb.tileSize, 85 + row * cb.tileSize);
            isWhite = !isWhite;
        }
    }
}

内容的提问来源于stack exchange,提问作者NotQuiteSoInvisible

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:05