简体   繁体   English

Java中的GUI线程

[英]GUI threading in java

I'm trying to code a simple game in Java. 我正在尝试用Java编写一个简单的游戏。 The basic structure is a single JFrame with different JPanels that I add/remove at different times. 基本结构是一个具有不同JPanels JFrame ,我在不同时间添加/删除了它。 At startup, there is a JPanel that's a basic menu (start game, high scores, etc). 在启动时,有一个JPanel是基本菜单(启动游戏,高分等)。 Once the "Start" button is pressed it switches to a level selector panel with three buttons to select the difficult level of the game. 一旦按下“开始”按钮,它将切换到带有三个按钮的级别选择器面板,以选择游戏的难度级别。 Once any of the three buttons is pressed, it switches to another panel that will displays a three second countdown, then the actual game. 一旦按下三个按钮中的任何一个,它将切换到另一个面板,该面板将显示三秒钟的倒数,然后显示实际的游戏。 All three buttons call the same method, just with a different difficulty value passed in. 这三个按钮都调用相同的方法,只是传递了不同的难度值。

I have all the separate pieces working fine, but I'm having troubles with the transition from the level selection panel to the countdown. 我所有的各个部分都工作正常,但是从级别选择面板到倒数计时的转换遇到了麻烦。 If I don't use threads the screen freezes on button press and does not switch to the new panel. 如果我不使用线程,则按按钮时屏幕会冻结,并且不会切换到新面板。 I've tried messing around with threads, but I don't know that much about them and have only had limited success (I've got it so it will successfully switch some of the time, but not consistently). 我已经尝试过弄乱线程,但是我对线程了解不多,而且只能取得有限的成功(我已经掌握了它,因此它可以在某些时间成功切换,但不能始终如一)。

In terms of code, in the level selection panel I have something like this listening for button clicks: 在代码方面,在级别选择面板中,我听到了类似这样的内容:

private class ButtonClickedListener implements ActionListener {
    public void actionPerformed(ActionEvent evt) {  
        gui.newLevel(1);
    }
}

where in place of just gui.newLevel(1) I've messed around with starting new threads and calling the method from them. 我只用gui.newLevel(1)代替了启动新线程并从中调用方法。

The newLevel() method look like: newLevel()方法如下所示:

getContentPane().removeAll();

levelPanel = new LevelPanel(levelNum, this);
add(levelPanel);
validate();

levelPanel.start();

I use very similar code when switching from the start menu JPanel to the level selector panel (again, with an ActionListener on the buttons), which works just fine. 从开始菜单JPanel切换到级别选择器面板(再次在按钮上带有ActionListener )时,我使用非常相似的代码,效果很好。

LevelPanel's start() method initializes values for the new JPanel and displays the countdown on screen (currently with the following code, although I messed with putting something like this in the newLevel() method instead) before displaying the actual game: LevelPanel的start()方法初始化新JPanel值并在屏幕上显示倒计时(当前使用以下代码,尽管我在将这样的东西放入newLevel()方法中弄乱了),然后才显示实际的游戏:

try {
    Thread.sleep(1000);
    //update countdown number
    validate();
    repaint();
    Thread.sleep(1000);
    //update countdown number
    validate();
    repaint();
    Thread.sleep(1000);
    //update countdown number
    validate();
    repaint();
} catch (Exception e) {
    System.out.println(e);
}

//start game

I would really appreciate any help getting this code to work, and I'm pretty sure some sort of threading is the way to go but I'm not quite sure where/how. 我真的很感谢能使此代码正常工作的任何帮助,而且我很确定某种方式的线程化是可行的方法,但是我不确定在哪里/如何做。 Any suggestions and/or code samples would be great! 任何建议和/或代码示例都很棒!

Thanks in advance! 提前致谢!

EDIT: I ended up rewriting the countdown using a timer instead of Thread.sleep() , which fixed part of the problem and the rest of it I eventually figured out and was entirely unrelated to GUI stuff, which is why I didn't think to check it in the first place. 编辑:我最终使用计时器而不是Thread.sleep()重写了倒数计时,从而解决了部分问题,最终我发现了其余问题,并且与GUI完全无关,这就是为什么我没有想到首先检查它。

never really never use Thread.sleep(1000); 从未真正从未使用过Thread.sleep(1000); during EDT, this code caused freeze on GUI is un_resposible, untill a new event invoke EDT or mouse hover over can alive this container too 在EDT期间,导致在GUI上冻结的此代码不可恢复,直到新事件调用EDT或鼠标悬停也可以使该容器存活

1) there are two ways how to dealy any event(s) in the Swing GUI, by implements 1)有两种方法可以通过Swing工具在Swing GUI中处理任何事件

  • Swing Timer

  • delaying by using Thread.sleep(1000); 通过使用Thread.sleep(1000);延迟Thread.sleep(1000); in the SwingWorker SwingWorker

The layout and painting must be done in EDT. 布局和绘画必须在EDT中完成。 Use SwingUtilities.invokeAndWait to call the validate() and repaint() 使用SwingUtilities.invokeAndWait调用validate()repaint()

You can start some code with a time delay using TimerTask: 您可以使用TimerTask延时启动一些代码:

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    public void run() {
        invokeLater(); // This starts after [delay] ms 
        // and - if given - will run every [period] ms.
    }
}, delay, period);

You could solve your problem with this, though it won't be a pretty solution. 尽管这不是一个很好的解决方案,但您可以解决您的问题。

// edit: (see comments) you should synchronize accesses to the gui properly, else it will give you errors. //编辑:(请参见注释),您应该正确同步对gui的访问,否则会给您错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM