2012-12-26 34 views
2

爲什麼下面的代碼不起作用?基本上,這是一個更困難的程序的簡化版本,我在其中嘗試創建一個可運行的初始屏幕,然後將選擇按鈕鏈接到不同的可運行的按鈕,但這並不像我預期的那樣運行。從另一個Runnable中運行Runnable的Java將不起作用

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class Runnables { 
    static Runnable runone; 
    static Runnable runtwo; 
    static JFrame frame = new JFrame(); 
    static JButton button1 = new JButton("Initial screen"); 
    static JButton button2 = new JButton("After button click screen"); 

    public static void main(String[] args) { 
     runone = new Runnable() { 
      @Override 
      public void run() { 
       frame.removeAll(); 
       frame.revalidate(); 
       frame.repaint(); 
       frame.add(button2); 
      } 

     }; 
     runtwo = new Runnable() { 
      @Override 
      public void run() { 
       frame.setSize(800, 600); 
       frame.setVisible(true); 
       button1.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent arg0) { 
         runone.run(); 
         System.out 
           .println("This is performed, but the button doesnt change"); 
        } 
       }); 
       frame.add(button1); 
      } 
     }; 
     runtwo.run(); 
    } 
} 
+0

您是否嘗試過在你的第一個可運行來驗證添加調試語句?正如所寫的,它只是一個直接的函數調用,沒有什麼特別的... – Krease

回答

4

Runnable沒有什麼特別的,可以防止這種情況發生。當你的代碼示例代表,下面是等價的:

public void actionPerformed(ActionEvent arg0) { 
    runone.run(); 
    System.out.println("This is performed, but the button doesnt change"); 
} 

public void actionPerformed(ActionEvent arg0) { 
    frame.removeAll(); 
    frame.revalidate(); 
    frame.repaint(); 
    frame.add(button2); 
    System.out.println("This is performed, but the button doesnt change"); 
} 

以你的代碼,並添加內runone.run一個System.out.println調試聲明表明,它實際上是在執行。

我假設你的代碼示例是一個簡化的問題演示;你可能希望首先考慮讓它做一個你想做的'純函數'(我的第二個例子,Runnables被合併),然後分離成不同的Runnables。

編輯 - 讓您的示例工作,需要記住的是,JFrame使用的contentPane主辦的孩子 - frame.add存在爲方便添加到contentPane(基於javadoc for JFrame),但removeAll不會這樣做(基於我剛剛玩它)。此外,在添加按鈕後調用validate將再次正確地重新佈局子組件,讓您的第二個按鈕出現。

與此一替換您的runone定義,您的樣品將工作:

runone = new Runnable() { 
    @Override 
    public void run() { 
     frame.getContentPane().removeAll(); 
     frame.add(button2); 
     frame.validate(); 
    } 
}; 
+0

所以這是我小的情況下,正確的解決方案,但我更大的情況下,從幾個按鈕,然後在窗口中所做的每個按鈕導致遊戲(在不同的語言),不runnable.run工作是()或SwingUtilities.InvokeLater(runnable); –

+0

嘗試在調試器中逐步完成它 - Runnables中的語句將被執行(只需添加斷點或調試語句來證明它);他們內部的陳述的正確性通常很重要。一個好的調試器將幫助您更清楚地看到代碼流,並幫助您關注各個狀態的狀況以及可能出錯的地方。 – Krease

3

你應該先封裝一個 Thread對象中的 Runnable對象,然後通過調用 start()啓動你的線程。例如:

Runnable r = ...; 
Thread thread = new Thread(r); 
thread.start(); 


編輯:

您應該確保調用您的Runnable的從EDT。例如:

SwingUtilties.invokeLater(r); 

或者你可以使用SwingWorker對付了涉及擺動代碼密集型操作。瞭解SwingWorker的工作方式,請參閱this answer

+0

你能舉一個簡短的例子嗎? –

+0

@ user268396我更新了我的答案。請看看它。 –

+0

改變你的答案,線程談話只會掩蓋有效點。 – user268396