为什么我不能使用 while 循环在我的桌面上绘制棋盘,但在我的笔记本电脑上可以?

问题描述 投票:0回答:1

我正在尝试使用 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++;
                
            }
            
        }
        
    }
    
}

奇怪的是,这段代码在我的笔记本电脑上运行完美,但是当我将它导出到我的桌面时,却出现了这个问题。 this is what it looks like on my laptop, which weirdly works this is what it looks like on my desktop, and it shows the board correctly for a split second

java swing draw drawable
1个回答
1
投票

这在很多层面上都是有问题的...

public class TileManager {

    private static int rows = 0;
    private static int cols = 0;

    //...
    public void drawTiles(Graphics g) {
        //...
        while (rows < cb.rows && cols < cb.cols) {

问问自己这个问题,下一次油漆通过会发生什么?

Swing 中的绘画具有破坏性。也就是说,在每个新的绘制过程中,您都应该从头开始完全重新绘制组件的状态。

paintComponent
要做的一件事是用组件的背景色填充
Graphics
上下文。

所以,在随后的绘画过程中,

rows
cols
已经是
>=
cb.rows
cb.cols
所以你代表什么都不会画。

首先,删除

static
,它在这种情况下对您没有任何帮助,并且可能会给您带来更多问题,然后再解决。其次,
rows
cols
不需要是实例级变量,它们的唯一作用是支持网格的绘制,所以你可以做局部变量代替。

例如...

public class TileManager {

    ChessBoard cb;
    public int[] types = new int[10];
    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;
        
        int rows = 0;
        int cols = 0;

        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
一个
ChessBoard
的实例是不好的做法,你向
TileManager
暴露了更多的功能然后它有任何管理责任。

就代码而言,我看不出有任何理由,但如果您确实需要

TileManager
从中提取信息,我会考虑编写一个
interface
来定义合同,或者,只需
ChessBoard 
设置
TileManager
的属性。任何返回通信都应该通过观察者模式完成(所以
TileManager
并告诉感兴趣的人,有些事情已经发生了)

我建议更加关注 AWT 和 Swing 中的绘画

关于“为什么”它在一个平台上工作而不在另一个平台上工作的问题,欢迎来到这个美妙的世界,这就是不同平台的工作方式——但有些事情会触发 Swing 在初始绘制通过后执行一个或多个绘制通过。

当我测试它(在 MacOS 上)时,它一直有效,直到我尝试重新调整窗口大小。

© www.soinside.com 2019 - 2024. All rights reserved.