2013-03-27 125 views
0

我正在嘗試構建一個簡單的tictactoe網絡遊戲。我需要該節目等待,直到一名球員進行動作,然後繼續。在我的代碼底部的whileConnected()函數中,我有一個while(true)循環,它應該永遠運行,並在按下按鈕時顯示一條確認消息(這是通過字符串的內容變量'消息'的變化)。暫停並等待按鈕被點擊,然後繼續

的問題是,即使單擊按鈕時字符串消息變量的變化,我的whileConnected()函數從不認識到這一點,並在函數內部的if語句永遠計算爲真。 ButtonListener類中的相同if語句正常工作並顯示所需的確認消息。

我該如何解決這個問題?我已閱讀和閱讀,並得到了我應該使用線程的想法(我閱讀了它們,但之前從未使用它們,這就是爲什麼它只是一個猜測)。我需要線程嗎?有人能簡單地解釋應該用於這個特定問題的原則嗎? (如何讓程序暫停,直到點擊按鈕,然後繼續使用點擊按鈕時創建的相關信息)。一個代碼示例會真正減輕我對線程的閱讀 - 當一個人是初學者時,這是一個非常抽象的主題。

下面是我的代碼,在此先感謝。

public class Test extends JFrame 
{ 
    private Container contentPane; 
    private JButton btn00; 
    private static String message = ""; 

    private class ButtonListener implements ActionListener 
    { 

     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      String buttonText = e.getActionCommand(); 

      if (buttonText.equals("My Button")) 
      { 
       message = "pressed"; 
       if (message != "") 
        System.out.println(message+"(executed by ButtonListener)"); 
      }   
     } 

    } 

    public Test() 
    { 
     this.contentPane = this.getContentPane(); 
     btn00 = new JButton("My Button"); 
     btn00.setSize(btn00.getPreferredSize()); 
     btn00.setLocation(20,20); 
     ButtonListener listener = new ButtonListener(); 
     btn00.addActionListener(listener); 

     // configure frame 
     this.setSize(300,300); 
     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 

     // make panel 
     JPanel panel = new JPanel(); 
     panel.setSize(200,200); 
     panel.setLocation(10,10); 
     panel.add(btn00); 
     this.contentPane.add(panel);   
    } 

    public static void main(String[] args) 
    { 
     Test gui = new Test(); 
     gui.setVisible(true); 
     // connected 
     whileConnected(); 

    } 

    private static void whileConnected() 
    { 
     System.out.println("message is at first empty: "+message); 
     while (true) 
     { 
      // the if below never evaluates to true... why? 

      if (message != "") // this is never true 
       System.out.println(message+"(executed by whileConnected)");   
     } 

    } 

} 

回答

2

如果你正在使用swing,你已經使用了線程。 Swing本質上有一個用於I/O的線程和一個用於後端的線程。你確實想要在這裏使用線程 - 除此之外,讓線程等待比爲它提供無限循環更便宜。

監聽器都是線程的另一種應用,我也不會感到驚訝,如果你能得到的大多數或所有你想要的只是通過構建良好的聽衆。或者,這些東西叫做信號量。信號量是線程處理時序的一種方式 - 如果一個線程試圖鎖定一個已經被鎖定的信號量,它將等待另一個線程在繼續(並再次鎖定)之前解鎖它。在你的情況下,你可以嘗試以下。

  • 有一個按鈕偵聽器,一個主函數和一個鎖定的信號量。
  • 主要功能啓動,執行任何初始行爲,並嘗試獲取信號量。因爲信號量已經被鎖定,它就成立了。
  • 當按鈕偵聽器觸發時,它所做的一件事是解鎖信號量。
  • 只要旗語解鎖,主要功能抓住它(從而鎖定了一次以上),並做什麼它應該做的事。最終,它結束並試圖再次獲取(鎖定的)信號量,從而等待下一次按鈕偵聽器觸發。
  • 重複。

編輯:包括並解釋實際接受的解決方案(來自以下評論)。

修復:添加Thread.sleep(1000);在whileConnected功能while循環的內部。

說明:while循環是一個無限循環,它包含只是一個if語句。這個if語句在很長一段時間內(至少就計算機而言)評估爲false(因此不會做任何進一步處理)。這與電短路的作用相同 - 沒有什麼可以減慢它的速度,所以運行該主函數的線程會燒燬大量的計算資源。這不好。一些故障安全可能會踢入並殺死線程。線程有可能以一種醜陋的方式失敗或破壞了某些東西。在任何情況下,包括一個睡眠語句(在這種情況下,每秒睡眠一次,因爲它以毫秒爲單位)可以防止這種情況發生,從而允許該函數無限期地繼續。

+0

「如果你能通過使用結構良好的聽衆獲得大部分或全部想要的東西,我不會感到驚訝。你能詳細解釋一下嗎? (我很欣賞信號量的細節,但現在對我來說太複雜了,這是一個我很快就需要解決的學校項目,所以我現在很樂意去尋求最簡單的解決方案) – 2013-03-27 20:12:46

+0

就像你需要的是一些能夠對按鈕進行適當反應的東西。你有一個按鈕監聽器,它執行基於按鈕按下的代碼。而不是在主函數中執行任何事情,你可以在監聽器中完成你需要做的所有事情。請注意,聽衆與用戶界面運行的線程相同,因此,如果有很多處理過程,那麼您可能會遇到一些令人不快的放緩,但它應該起作用。不幸的是,如果你的問題標題是你的任務的直接引用,信號量可能是他們正在尋找的。 – 2013-03-27 20:16:40

+0

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html在這裏可能會有所幫助,如果您確實需要使用信號量。 – 2013-03-27 20:20:54

0

我認爲遊戲暫停直到按下按鈕,因爲GUI不會運行主線程,它應該在事件分派線程中運行。

Swing肯定有很多關於線程和偵聽器的問題,如果執行不正確,可能會導致一些不可預知的行爲。

你有沒有通過甲骨文的Java教程Swing?大多數relavent將是http://docs.oracle.com/javase/tutorial/uiswing/events/index.html聽衆和例子http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html爲WorkerThreads

我與Swing中發現的最好的事情就是在這裏下載例子並嘗試對他們

我雖然本·巴登同意擴大,根據我對你需要的理解,我認爲你可以用聽衆來實現你所需要的東西。

+0

我相信你的意思是你同意我的意見。 Assylias編輯了這篇文章,但沒有對此做出迴應。另外,歡迎來到Stack Overflow。 :) – 2013-03-27 19:41:22

+0

哎呀!謝謝本:) – Causteau 2013-03-27 19:54:32

1

像大多數GUI框架一樣,Swing是一個事件驅動的環境。基本上這意味着,應用程序將等待某種事件發生,然後觸發正在等待該事件通知的任何已註冊的偵聽器。

在你的情況下,你只需要註冊一個AdtionListener到按鈕。當用戶點擊它(或通過鍵盤激活)時,將調用actionPerformed方法,並且您可以執行您需要的任何代碼。

查看更多信息How to write action listeners

Swing也是單線程framwework。也就是說,所有與UI的交互都必須在事件派發線程的上下文中執行。

這也意味着,任何長時間運行或阻塞的任務都必須從一個單獨的線程中執行,以免阻止EDT處理傳入事件和重繪請求,這可能會使應用程序看起來好像掛起了。

退房Concurrency in Swing更多細節

在我看來,你的遊戲協議將需要追蹤的方式,其圍繞它。這可以簡單地通過使用虛擬令牌來實現。

基本的概念是,除非玩家有令牌,否則他們不能動。一旦玩家移動,該移動和令牌就會發送給其他玩家。

相關問題