Why can I not use a while loop to draw a chessboard on my desktop, but can on my laptop?

huangapple go评论57阅读模式
英文:

Why can I not use a while loop to draw a chessboard on my desktop, but can on my laptop?

问题

I'm trying to make a chess board using a while loop. However when I use a while loop, the tiles show up for a second and then they disappear.

The code for the panel:

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 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);
    }
}

the code for the drawing:

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++;
            }
        }
    }
}

The weird thing about this is that this code works perfectly on my laptop, but when I exported it to my desktop, it has this problem.

英文:

I'm trying to make a chess board using a while loop. However when I use a while loop, the tiles show up for a second and then they disappear.

The code for the panel

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);
}
}

the code for the drawing

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 = {&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;, &quot;g&quot;, &quot;h&quot;};
String [] num = {&quot;8&quot;, &quot;7&quot;, &quot;6&quot;, &quot;5&quot;, &quot;4&quot;, &quot;3&quot;, &quot;2&quot;, &quot;1&quot;};
TileManager(ChessBoard cb){
this.cb = cb;
}
public void drawTiles(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
while (rows &lt; cb.rows &amp;&amp; cols &lt; cb.cols) {
if (c)	g.setColor(Color.white);
if (!c) g.setColor(Color.black);
g2.setFont(new Font(&quot;Comic Sans&quot;, 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++;
}
}
}
}

The weird thing about this is that this code works perfectly on my laptop, but when I exported it to my desktop, it has this problem.
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

答案1

得分: 1

以下是您要翻译的内容:

This is problematic on a number of levels...
这在多个层面上都存在问题...

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

Ask yourself the question, what happens on the next paint pass?
请问一下,下一个绘制过程会发生什么?

Painting in Swing is destructive. That is, on each new paint pass, you're expected to completely repaint the state of the component, from scratch.
Swing中的绘制是破坏性的。也就是说,在每次新的绘制过程中,您应该从头开始完全重新绘制组件的状态。

One of the things paintComponent will do is fill the Graphics context with the background color of the component.
paintComponent的一个任务是使用组件的背景颜色填充Graphics上下文。

So, on subsequent paint passes, rows and cols are already &gt;= cb.rows and cb.cols so your delegate will paint nothing.
因此,在后续的绘制过程中,rowscols已经&gt;= cb.rowscb.cols,因此您的代理将不会绘制任何内容。

First, remove static, it's not doing your any favours in this context and will probably cause you more issues then it solves. Second, rows and cols don't need to be instance level variables, their only function is to support the painting of the grid, so you can make them local variables instead.
首先,移除static,在这个上下文中它没有任何好处,而且可能会引发更多问题。其次,rowscols不需要是实例级变量,它们的唯一功能是支持网格的绘制,因此您可以将它们改为局部变量。

For example...
例如...

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 &lt; cb.rows &amp;&amp; cols &lt; 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++;
}
}
}

}

I, personally, would consider it bad practice to pass TileManager an instance of ChessBoard, you're exposing WAY more functionality to TileManager then it has any responsibility for managing.
我个人认为,将TileManager传递给ChessBoard的实例是不好的做法,您向TileManager暴露了比其管理职责更多的功能。

As the code stands, I don't see any reason for it, but if you did need TileManager to pull information from it, I'd consider writing an interface which defined the contract, or, simply have ChessBoard set the properties of the TileManager. Any return communication should be done via an observer pattern (so TileManager can tell, whoever is interested, that something has happened).
就目前的代码而言,我没有看到这样做的理由,但如果您确实需要TileManager从中获取信息,我建议编写一个定义了合同的interface,或者简单地让ChessBoard设置TileManager的属性。任何返回的通信都应通过观察者模式来完成(这样TileManager可以告诉感兴趣的任何人发生了什么)。

I would suggest paying closer attention to Painting in AWT and Swing.
我建议更加关注AWT和Swing中的绘制

As to the question of "why" it works on one platform and not another, welcome to the wonderful world of, that's how different platforms work - but some thing is triggering Swing to perform one or more paint passes after the initial paint pass.
至于“为什么”它在一个平台上运行而在另一个平台上不运行,欢迎来到不同平台的奇妙世界 - 但某些事情会触发Swing在初始绘制后执行一个或多个绘制过程。

When I tested it (on MacOS), it worked right up to the moment I tried re-sizing the window.
当我在MacOS上测试时,它一直运行正常,直到我尝试调整窗口大小的那一刻。

英文:

This is problematic on a number of levels...

public class TileManager {
private static int rows = 0;
private static int cols = 0;
//...
public void drawTiles(Graphics g) {
//...
while (rows &lt; cb.rows &amp;&amp; cols &lt; cb.cols) {

Ask yourself the question, what happens on the next paint pass?

Painting in Swing is destructive. That is, on each new paint pass, you're expected to completely repaint the state of the component, from scratch.

One of the things paintComponent will do is fill the Graphics context with the background color of the component.

So, on subsequent paint passes, rows and cols are already &gt;= cb.rows and cb.cols so you delegate will paint nothing.

First, remove static, it's not doing your any favours in this context and will probably cause you more issues then it solves. Second, rows and cols don't need to be instance level variables, their only function is to support the painting of the grid, so you can make then local variables instead.

For example...

public class TileManager {
ChessBoard cb;
public int[] types = new int[10];
private boolean c = true;
String[] alpha = {&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;, &quot;g&quot;, &quot;h&quot;};
String[] num = {&quot;8&quot;, &quot;7&quot;, &quot;6&quot;, &quot;5&quot;, &quot;4&quot;, &quot;3&quot;, &quot;2&quot;, &quot;1&quot;};
TileManager(ChessBoard cb) {
this.cb = cb;
}
public void drawTiles(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int rows = 0;
int cols = 0;
while (rows &lt; cb.rows &amp;&amp; cols &lt; cb.cols) {
if (c) {
g.setColor(Color.white);
}
if (!c) {
g.setColor(Color.black);
}
g2.setFont(new Font(&quot;Comic Sans&quot;, 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++;
}
}
}
}

I, personally, would consider it bad practice to pass TileManager an instance of ChessBoard, you're exposing WAY more functionality to TileManager then it has any responsibility for managing.

As the code stands, I don't see any reason for it, but if you did need TileManager to pull information from it, I'd consider writing an interface which defined the contract, or, simply have ChessBoard set the properties of the TileManager. Any return communication should be done via an observer pattern (so TileManager and tell, who ever is interested, that some has happened)

I would suggest paying closer attention to Painting in AWT and Swing.

As to the question of "why" it works on one platform and not another, welcome to the wonderful world of, that's how different platforms work - but some thing is triggering Swing to perform one or more paint passes after the initial paint pass.

When I tested it (on MacOS), it worked right up to the moment I tried re-sizing the window.

huangapple
  • 本文由 发表于 2023年2月18日 09:51:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75490691.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定