2012-02-29 48 views
0

我想在Java中編寫一個簡單的遊戲。基本結構是一個單獨的JFrame,不同的JPanels我在不同的時間添加/刪除。在啓動時,有一個JPanel這是一個基本的菜單(開始遊戲,高分等)。一旦按下「開始」按鈕,它將切換到帶三個按鈕的水平選擇器面板,以選擇難度較高的遊戲。一旦三個按鈕中的任何一個被按下,它就會切換到另一個顯示三秒鐘倒計時的面板,然後是實際的遊戲。所有三個按鈕調用相同的方法,只是通過一個不同的難度值。在Java中的GUI線程

我有所有單獨的部分工作正常,但我有麻煩從級選擇面板到倒計時的過渡。如果我不使用線程,屏幕會在按下按鈕時凍結,並且不會切換到新面板。我嘗試過使用線程搞亂,但我對它們並不瞭解,只有有限的成功(我已經掌握了它,所以它會成功切換一些時間,但並不一致)。

在代碼方面,在級別選擇面板我有這樣的事情監聽按鈕點擊:

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

其中地方只是gui.newLevel(1)我已經開始新的線程和調用方法好惹的從他們。

newLevel()方法是這樣的:

getContentPane().removeAll(); 

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

levelPanel.start(); 

從開始菜單JPanel電平選擇面板切換時(再次,鈕釦上鑲有一個ActionListener),這只是罰款我使用非常相似的代碼。

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 

我真的很感謝任何幫助獲得這個代碼的工作,我敢肯定某種線程是要走的路,但我不太確定在哪裏/如何。任何建議和/或代碼示例都會很棒!

在此先感謝!

編輯:我結束了使用定時器來代替Thread.sleep(),其中固定的問題和它的其餘部分的一部分,我終於想通了,是完全無關的GUI東西改寫倒計時,這就是爲什麼我沒有」我認爲首先要檢查它。

回答

5

佈局和繪畫必須在EDT中完成。使用SwingUtilities.invokeAndWait調用validate()repaint()

+0

你可以提供一些示例代碼,以瞭解這將如何工作? – scaevity 2012-02-29 08:25:31

+0

此外,在我的代碼中應特別使用invokeAndWait()嗎? – scaevity 2012-02-29 08:59:53

+0

'invokeAndWait'往往會導致死鎖。 'invokeLater'通常是一個更好的主意。 – 2012-02-29 23:18:48

6

從來沒有真正EDT時從來不使用Thread.sleep(1000);,這段代碼造成了GUI凍結是un_resposible,直到一個新的invoke EDT或事件鼠標懸停在可以活着這個容器也

1)有兩種方法如何迪利在Swing GUI的任何事情(S),通過工具

  • Swing Timer

  • 通過在SwingWorker

+0

你能給我一個(或兩個)這些(與代碼)的例子嗎?我沒有使用Swing Timer,並且我努力讓SwingWorker工作到目前爲止還不是很成功。 – scaevity 2012-02-29 08:31:59

+1

@scae [Swing Timer](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)---> [我的帖子在這裏](http://stackoverflow.com/search? tab = newest&q = user%3a714968%20timer)和[SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html)---> [我的帖子在這裏](http:/ /stackoverflow.com/search?tab=newest&q=user%3a714968%20swingworker) – mKorbel 2012-02-29 08:42:54

0

使用Thread.sleep(1000);延遲可以使用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); 

你可以用這個解決您的問題,但它不會是一個漂亮的解決方案。

//編輯:(見評論)你應該正確地同步訪問gui,否則會給你錯誤。

+1

請編輯你的文章並將'doSomething();'包裝到'invokeLater()'中,否則你可以等待幾個down_votes到你真正錯誤的答案造成與OP相同的問題。 – mKorbel 2012-02-29 08:11:34

+1

*「這不會是一個漂亮的解決方案。」*除非在EDT上完成GUI更新,否則它將不是一個解決方案。這就是['javax.swing.Timer'](http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html)和'SwingWorker'派上用場的地方。 – 2012-02-29 08:13:47

+0

@mKorbel打我!給正確的答案和正確的評論。 :) – 2012-02-29 08:14:49