2015-02-09 58 views
1

#1親愛的朋友們,的ActionListener和循環

這裏是我想要做的事: - 我想有一些按鈕和一個JTextArea 一個簡單的框架 - 我想有一個循環在每一次迭代中,我都希望點擊一個按鈕:當我點擊這個按鈕時,發生了一堆事情,但我無法正確理解: - 我一次嘗試使用for循環工作,但它不會停下來,在任何一個輪次,它只是採取了第一個命令,並執行了所有20回合沒有停止 - 在當前版本中,我點擊按鈕,沒有任何反應 - 我已經研究了SOF和一系列其他網站,包括奧拉CLE文件,但(可能也是由於我的經驗水平),我無法找到一個解釋,即是非常明顯的,我聽不懂

這裏我的代碼

package game4_prova_forloop; 

import java.awt.Color; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.GroupLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 

public class GAME4_prova_forloop { 

    public static void main(String[] args) { 

     //create frame 
     JFrame frame = new JFrame("Action Listener"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(600, 600); 
     frame.setLayout(new FlowLayout()); 
     frame.setVisible(true); 

     //crete text area panel, 
     JPanel pannelloTextArea = new JPanel(); 
     pannelloTextArea.setBackground(new Color(255, 204, 204)); 
     pannelloTextArea.setSize(400, 400); 
     frame.add(pannelloTextArea); 
     GroupLayout pannelloTextAreaLayout = new GroupLayout(pannelloTextArea); 

     //create scrollPane 
     JScrollPane scrollTextArea = new JScrollPane(); 

     //1) create JTextArea 
     JTextArea mostraTesto = new JTextArea(20, 20); 
     mostraTesto.setLineWrap(true); //make it wrap text 
      pannelloTextArea.add(scrollTextArea); //add it to scroll pane 
      pannelloTextArea.revalidate(); 
       scrollTextArea.add(mostraTesto); //add the scroll pane to text area 
       scrollTextArea.setViewportView(mostraTesto); 

     //2) create buttons 
     JButton action1 = new JButton("1"); 
     frame.add(action1); 
     JButton action2 = new JButton("2"); 
     frame.add(action2); 
     JButton action3 = new JButton("3"); 
     frame.add(action3); 

     //3) pass textArea in the RoundLevelAction class 
     RoundLevelAction roundLevelActionObj = new RoundLevelAction(mostraTesto); //first issue: I get an error 
     //4) add listener to JButtons 
     action1.addActionListener(roundLevelActionObj); 
     action2.addActionListener(roundLevelActionObj); 
     action3.addActionListener(roundLevelActionObj);   
    } 

//THIS IS WHERE I START TO HAVE PROBLEMS: WHEN I CLICK NOTHING HAPPENS, WHEN 
//I WOULD EXPECT THE FOR LOOP TO GO THROUGH ITERATIONS 
    public class RoundLevelAction implements ActionListener { 

     //add inside the listener the pieces of GUI that you'll use 
     private JTextArea mostraTesto; 
     private Object action1; 
     private Object action2; 
     private Object action3; 
     private Object action4; 
     private Object action5; 
     private Object action6; 

     //create class for JTextArea 
     public RoundLevelAction(JTextArea mostraTesto){ 
      this.mostraTesto = mostraTesto; 
     }  

     //and, finally, what I really want to do: a loop that, at each turn, expects me to click on 
     //a button and does an action in response 
     public void actionPerformed(ActionEvent e) { 
      //now create the loop 
      for (int round_counter=1; round_counter<21; round_counter++) {          
       if (e.getSource()==action1){        
        mostraTesto.append("\n description action 1 and a bunch of other stuff"); 
       } 
       else if (e.getSource()== action2){ 
        mostraTesto.append("\n description action 2 and a bunch of other stuff"); 
       } 
       else if (e.getSource()== action3){ 
        mostraTesto.append("\n description action 3 and a bunch of other stuff"); 
       } 
      } 
     } 
    } 

} 

重要:我清楚地知道,上面的代碼不適合Java最佳實踐:它只是一個示例代碼來說明我正在嘗試做什麼(原始代碼是多個類中的很多行)

我希望你能幫助我理解我在哪裏做錯了

非常感謝提前

回答

2

爲什麼您的代碼目前無法正常工作,以及您之前的嘗試可能存在什麼問題。

action1.addActionListener(roundLevelActionObj); 
action2.addActionListener(roundLevelActionObj); 
action3.addActionListener(roundLevelActionObj); 

這將爲您的每個按鈕添加相同的偵聽器。當您點擊這些按鈕時,將生成一個ActionEvent併發送到ActionListener

當您在ActionListener中有一個for循環時,每次單擊這些按鈕時都會執行整個循環。它是執行actionPerformed方法中的整個代碼塊。這可能是你在第一次嘗試時發現的。

您當前的嘗試在for循環中有if (e.getSource()==action1)檢查。但是,該語句中的action1與您單擊的按鈕不同。該action1這裏指的是外地

private Object action1; 

RoundLevelAction類。如果您使用調試器,則會看到這些if語句中沒有一個語句的結果爲true,這就是您沒有任何反應的印象的原因。 實際上,for循環被觸發,但沒有輸出,因爲沒有任何if語句評估爲true。

如果您使用調試器並放置一些斷點,上述所有內容都很容易被發現。

現在爲您的問題的解決方案。我不清楚這一點。

我想有一個循環,在每次迭代,希望我 點擊一個按鈕

這項規定的問題是,Swing是單線程的。這意味着所有與Swing相關的操作應該發生在單個線程上(E(vent)D(ispatch(T(hread)),並且該線程用於處理用戶輸入(例如鼠標點擊)並繪製UI 。這也意味着,如果你以某種方式阻止單線程,你的用戶界面變得不負責任。

因此,如果你有一個循環,你不能簡單地阻止EDT並等待按鈕點擊,因爲EDT被阻塞,無法點擊EDT。

  • 要麼你在一個單獨的線程循環,並在該線程等待,直到用戶在按鈕上點擊。關聯到該按鈕的ActionListener可以重新激活螺紋
  • 您可以顯示一個對話框,詢問用戶下一步該做什麼,並將這些按鈕放入該對話框中。看看這個JOptionPane#show...方法。
+0

謝謝羅賓花時間解釋清楚。我在研究中發現了您的解決方案,但從未如此清楚地解釋過。所以,如果我正確地讀了你的話,這是一個完全改變邏輯並轉向多線程的問題。我最後一次尋求幫助是:你知道一個很好的教程,解釋如何做到這一點?我問,因爲當我在過去發現這個建議,並試圖按照教程,我永遠不能將它們應用到我的案例 – Bugbearvirus 2015-02-09 20:35:47

+0

,並澄清我想做的事情......這是一個簡單的遊戲:迭代開始 - >系統做這會影響你的生活點 - >你的按鈕會影響系統的生命點 - >下一次迭代。繼續進行20次迭代:如果你還活着,你贏了 – Bugbearvirus 2015-02-09 20:40:07

+0

@Bugbearvirus在這種情況下,我可能不會打擾一個單獨的線程。每次按下一個按鈕時,您都可以減少一個計數器。無需循環。但我看到你已經明白了你自己 – Robin 2015-02-10 08:33:23

0

羅賓的優秀答案,雖然不是一個直接的解決方案,但讓我想到了程序的邏輯,並問自己:爲什麼我有一個for循環呢?要計數從20迴轉到0? 呃..我總是可以數數(duh!)。所以我完全擺脫了for循環,爲其他每個ifs都設置了一個計數器++,並將所有內容封裝在一個if計數器中。< 20. 現在,每次迭代都由按鈕之一的壓力激活,迭代上去,遊戲遵循邏輯。 不是最好的解決方案,而是「一個」解決方案。 我希望這可以對另一個用戶有用