gpt4 book ai didi

java - 如何在方法中初始化后正确显示 JFrame

转载 作者:行者123 更新时间:2023-11-29 07:45:01 30 4
gpt4 key购买 nike

这是一个很长的问题,请耐心等待一分钟。我正在制作一个生命游戏应用程序,它首先显示一个带有 JButton 网格的 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);
}
}
}

在 main 方法中,我创建了此类的一个实例,当您选择要激活的按钮时,您可以单击 go 按钮实际显示 Game of Life。

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 网格。

只有当我使用全零数组 states 从 main 方法创建 Gui 实例时,它才会正确显示。我已经尝试了很多事情来提出解决方案,但我不明白为什么它会导致这个白屏而不是网格。因此我的问题是:如何正确显示我的 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 线程问题的典型案例,这是由于您的长时间运行代码也在 Swing 事件线程上调用了 Thread.sleep(...),这将使整个 GUI 进入休眠状态,这当然不是您的目标。

解决方案与任何类似问题相同(您应该在此处发布之前搜索并找到):使用 SwingWorker用于后台线程,如果你有长时间运行的代码,或者 Swing Timer用于延迟地循环调用代码。

在这里你使用哪个取决于 Maths.render 有多慢。如果这个计算速度非常快,那么你所需要的只是一个 Swing Timer 来间歇地和延迟地进行这个调用。如果此方法需要花费大量时间来执行,那么您将需要走 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();
}

关于java - 如何在方法中初始化后正确显示 JFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26619025/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com