【发布时间】:2020-03-26 01:06:17
【问题描述】:
我正在使用 Java Swing 编写俄罗斯方块。 Game 类围绕着一个 JFrame(框架),它由一个 TetrisPanel 扩展 JPanel(面板)组成,一个 JLabel(pontok)点计数器,一个显示高分的 JTextArea(rekord_text)和另一个显示高分的 JPanel(kovi)下一个要倒下的街区。我的想法是游戏有 3 个难度级别,其中积木以不同的速度下落。
我认为解决此问题的最佳方法是使用上述组件创建一个新的 JFrame,但块的速度设置不同。我能够关闭旧的 JFrame。但是当新的JFrame打开时,它只是一个空白框,并不会响应关闭窗口。
我应该补充一点,TetrisPanel 正在运行一个线程,但我 90% 确定我会用一个 volatile 布尔值来停止它。
游戏类的构造函数:
this.difSet(nehezseg); //this function sets the falling velocity
TetrisPanel.stopped = true; //this static member is the volatile boolean responsible for stopping the thread
new_game = false;
frame = new JFrame("Tetris_alpha");
frame.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
panel = new TetrisPanel();
TetrisPanel.stopped = false;
new Thread(panel).start();
frame.add(panel, c);
pontok = new JLabel ("0");
frame.add(pontok, c);
rekord_text = new JTextArea();
//i set up the area
frame.add(rekord_text, c);
kovi = new NextAktualPanel();
frame.add(kovi, c);
menu = new MyMenu(this);
frame.setJMenuBar(menu);
frame.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
rekordok.add(panel.getPont());
rekordok.write(f);
e.getWindow().dispose();
System.exit(0);
}
}
);
frame.pack();
frame.setVisible(true);
}
包含游戏循环的 Game.start() 函数:
public void start()
{
//game_loop
while (!panel.GameOver() && !new_game)
{
if (panel.aktualLeertDetector())
{
panel.addAktualToBlocks();
panel.addNewAktual(next);
Elem temp = new Elem(0,0,rand.nextInt(7));
while (temp.getTipus() == next.getTipus())
temp = new Elem(0,0,rand.nextInt(7));
next = temp;
kovi.setNextAktual (next);
}
if (!paused)
pontok.setText(Integer.toString(panel.getPont()));
kovi.repaint();
panel.repaint();
}
打开新框架的函数:
Public void newGame (Game g)
{
Game.new_game = true;
g.frame.dispose();
Game new_game = new Game("easy");
g = new_game;
g.start();
}
还有TetrisPanel的run()函数:
public static volatile boolean stopped = false;
@Override
public void run() {
while (!stopped)
{
aktual.zuhan();
this.sorTeleAction();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
任何帮助都将不胜感激,包括有关不同方法的想法。
【问题讨论】:
-
Swing 不应由 AWT 事件调度线程以外的线程使用。如果您想延迟时间,请使用
javax.swing.Timer(注意不要混淆使用同名的其他计时器)。 -
您的代码似乎违反了 Swing 线程规则。如果您还没有阅读Concurrency in Swing,那么现在是个好时机,因为此链接将解释这些规则、如何遵循它们以及它们为何重要。那么是的,按照@TomHawtin 的建议去做——使用Swing Timer 来驱动你的游戏循环。
-
我认为解决这个问题的最好方法是用组件创建一个新的 JFrame - 不需要创建一个新的 JFrame。您的游戏逻辑只需要一个“重置”方法。当您使用 JTextField 时,您只需使用
setText(...)来更改文本。当您使用 JTable 时,您只需更改 TableModel。在任何一种情况下,您都不会创建新组件。
标签: java swing jframe jpanel java-threads