英文:
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 = {"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.
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 >=
cb.rows
and cb.cols
so your delegate will paint nothing.
因此,在后续的绘制过程中,rows
和cols
已经>=
cb.rows
和cb.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
,在这个上下文中它没有任何好处,而且可能会引发更多问题。其次,rows
和cols
不需要是实例级变量,它们的唯一功能是支持网格的绘制,因此您可以将它们改为局部变量。
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 < 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++;
}
}
}
}
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 < 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.
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 >=
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 = {"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++;
}
}
}
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论