这是一个很长的问题,请耐心等待一分钟。我正在制作一个“生活游戏”应用程序,该应用程序首先显示带有JButtons网格的JFrame。如果单击JButton,其背景将变为黑色,再次激活后,其背景将变为白色。我的代码:
public class Choose implements ActionListener {
public final static int DIMENSION = 50;
Color BLACK = new Color(0,0,0);
Color WHITE = new Color(255,255,255);
JFrame choose;
JButton[] choice;
JButton clear, fill, go;
JPanel baseChoose, baseFrame, buttonsAndText;
GridLayout base;
public Choose() {
choose = new JFrame("Make your own game");
choice = new JButton[DIMENSION*DIMENSION];
baseChoose = new JPanel();
baseChoose.setSize(500, 500);
buttonsAndText = new JPanel();
buttonsAndText.add(clear = new JButton("Clear"));
clear.addActionListener(this);
buttonsAndText.add(fill = new JButton("Fill"));
fill.addActionListener(this);
buttonsAndText.add(go = new JButton("Go"));
go.addActionListener(this);
base = new GridLayout(DIMENSION, DIMENSION);
base.setHgap(-1);
base.setVgap(-1);
baseChoose.setLayout(base);
choose.add(baseChoose);
choose.add(buttonsAndText);
JLabel text = new JLabel("Press 'Go' to start.");
buttonsAndText.add(text);
for (int i = 0; i < (DIMENSION*DIMENSION); i++) {
baseChoose.add(choice[i] = new JButton());
choice[i].setBackground(WHITE);
choice[i].addActionListener(this);
}
choose.setSize(500, 800);
choose.setVisible(true);
choose.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
choose.setResizable(false);
}
public void actionPerformed(ActionEvent e) {
JButton b = (JButton)e.getSource();
for (int i = 0; i < (DIMENSION*DIMENSION); i++) {
if (b == choice[i]) {
if (b.getBackground() == BLACK) {
choice[i].setBackground(WHITE);
} else if (b.getBackground() == WHITE) {
choice[i].setBackground(BLACK);
}
}
}
if (b == clear) {
for (int i = 0; i < (DIMENSION*DIMENSION); i++) {
choice[i].setBackground(WHITE);
}
choose.validate();
choose.repaint();
}
if (b == fill) {
for (int i = 0; i < (DIMENSION*DIMENSION); i++) {
choice[i].setBackground(BLACK);
}
choose.validate();
choose.repaint();
}
if (b == go) {
int states[] = new int[DIMENSION*DIMENSION];
for (int i = 0; i < DIMENSION*DIMENSION; i++) {
System.out.println(choice[i].getBackground() == BLACK);
if (choice[i].getBackground() == BLACK) {
states[i] = 1;
} else if (choice[i].getBackground() == WHITE) {
states[i] = 0;
}
}
choose.dispose();
Gui own = new Gui(states);
}
}
}
在主要方法中,我创建了该类的一个实例,当您选择要激活的按钮时,可以单击该go
按钮以实际显示“生命游戏”。
public class Gui {
public final static int DIMENSION = 50;
Color BLACK = new Color(0,0,0);
Color WHITE = new Color(255,255,255);
JFrame frame, ownFrame;
JPanel baseFrame;
GridLayout base;
public Gui(int[] states) {
frame = new JFrame("Game of Life by Boris Verwoerd");
baseFrame = new JPanel();
baseFrame.setSize(500, 500);
frame.add(baseFrame);
base = new GridLayout(DIMENSION, DIMENSION);
base.setHgap(-1);
base.setVgap(-1);
baseFrame.setLayout(base);
JPanel[] box = new JPanel[DIMENSION*DIMENSION];
for (int i = 0; i < (DIMENSION*DIMENSION); i++) {
baseFrame.add(box[i] = new JPanel());
box[i].setBorder(BorderFactory.createLineBorder(Color.black));
}
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.validate();
frame.repaint();
gameLoop(box, frame, states);
}
private static void gameLoop(JPanel[] boxes, JFrame theFrame, int[] states) {
int[] newstates = new int[DIMENSION*DIMENSION];
for (int i = 0; i < 20; i++) {
newstates = Maths.render(boxes, theFrame, states);
states = newstates;
theFrame.validate();
theFrame.repaint();
try {
Thread.sleep(100); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public static int getDim() {
return DIMENSION;
}
}
当按下go键时,一个新的JFrame会启动,但屏幕完全是白色的,仅在gameLoop结束后才显示JPanel网格。
只有当我从main方法使用全零数组创建Gui的实例时,states
它才能正确显示它。我已经尝试了很多方法来提出解决方案,但是我不明白为什么它会导致白色屏幕而不是网格。因此,我的问题是:从方法初始化时,如何在没有白屏的情况下正确显示Gui的实例?
编辑:
这是我的数学课:
public class Maths {
static Color BLACK = new Color(0,0,0);
static Color WHITE = new Color(255,255,255);
public static int[] render(JPanel[] box, JFrame frame, int[] state) {
int[] newstates = new int[Gui.getDim()*Gui.getDim()];
for (int i = 0; i < (Gui.getDim()*Gui.getDim()); i++) newstates[i] = 0;
for (int i = (Gui.getDim()+1); i < (Gui.getDim()*Gui.getDim() - (Gui.getDim()+1)); i++) {
if (state[i] == 1) {
int aliveNeighbours = 0;
if (state[i-(Gui.getDim()+1)] == 1) aliveNeighbours++;
if (state[i-Gui.getDim()] == 1) aliveNeighbours++;
if (state[i-(Gui.getDim()-1)] == 1) aliveNeighbours++;
if (state[i-1] == 1) aliveNeighbours++;
if (state[i+1] == 1) aliveNeighbours++;
if (state[i+(Gui.getDim()-1)] == 1) aliveNeighbours++;
if (state[i+Gui.getDim()] == 1) aliveNeighbours++;
if (state[i+(Gui.getDim()+1)] == 1) aliveNeighbours++;
if (aliveNeighbours == 2 || aliveNeighbours == 3) {
box[i].setBackground(BLACK);
newstates[i] = 1;
} else {
box[i].setBackground(WHITE);
newstates[i] = 0;
}
} else if (state[i] == 0) {
int aliveNeighbours = 0;
if (state[i-(Gui.getDim()+1)] == 1) aliveNeighbours++;
if (state[i-Gui.getDim()] == 1) aliveNeighbours++;
if (state[i-(Gui.getDim()-1)] == 1) aliveNeighbours++;
if (state[i-1] == 1) aliveNeighbours++;
if (state[i+1] == 1) aliveNeighbours++;
if (state[i+(Gui.getDim()-1)] == 1) aliveNeighbours++;
if (state[i+Gui.getDim()] == 1) aliveNeighbours++;
if (state[i+(Gui.getDim()+1)] == 1) aliveNeighbours++;
if (aliveNeighbours == 3) {
box[i].setBackground(BLACK);
newstates[i] = 1;
} else {
box[i].setBackground(WHITE);
newstates[i] = 0;
}
}
}
return newstates;
}
}
您的问题是Swing线程问题的典型案例,这是由于您的代码运行时间很长,还需要调用Thread.sleep(...)
Swing事件线程,这会使整个GUI处于休眠状态,当然这不是您的目标。
解决方案与任何类似的问题相同(在此处发布之前,应该已经搜索并找到了类似的问题):如果您有长时间运行的代码,请使用SwingWorker进行后台线程处理,或者使用Swing计时器以延迟方式周期性地调用代码。
您在此处使用的速度取决于速度Maths.render
。如果计算速度非常快,那么您只需要一个Swing计时器即可间歇地且延迟地进行此调用。如果此方法需要大量时间才能执行,那么您将需要执行SwingWorker路线。
例如,计时器代码如下所示:
private void gameLoop() {
int timerDelay = 100;
new Timer(timerDelay, new ActionListener() {
private final int maxIndex = 20;
private int index = 0;
@Override
public void actionPerformed(ActionEvent e) {
if (index < maxIndex) {
states = Maths.render(box, frame, states);
frame.validate();
frame.repaint();
} else {
((Timer) e.getSource()).stop();
}
index++;
}
}).start();
}
注意gameLoop应该是一个非静态实例方法。我也不允许参数传递,而是使该类的这些家伙领域:
private JPanel[] box;
private int[] states;
并确保设置以下字段:
public Gui(int[] states) {
this.states = states;
frame = new JFrame("Game of Life by Boris Verwoerd");
baseFrame = new JPanel();
baseFrame.setSize(500, 500);
frame.add(baseFrame);
base = new GridLayout(DIMENSION, DIMENSION);
base.setHgap(-1);
base.setVgap(-1);
baseFrame.setLayout(base);
box = new JPanel[DIMENSION * DIMENSION];
for (int i = 0; i < (DIMENSION * DIMENSION); i++) {
baseFrame.add(box[i] = new JPanel());
box[i].setBorder(BorderFactory.createLineBorder(Color.black));
}
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.validate();
frame.repaint();
gameLoop();
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句