2012-01-30 63 views
4

我已經設法創建了一個打字機類,它能夠完成我想要的大部分功能。它會一次輸出給它一個字符的字符串,在每個字符之間暫停,就好像它們被鍵入一樣,在句點之後暫停一會兒。我現在遇到的問題是,當我使用這個類時,它只能工作一次。當我將它調用兩次(或更多)時,它會嘗試同時運行它們。這會導致重大問題。所以我需要一種方法讓這個類的第一個實例運行,並且每個在開始之前等待「輪到」。以下是期望的結果和當前的例子。使用JTextArea的打字機效果

import objectdraw.*; // Where active object comes from.  
import javax.swing.JTextArea; 

public class Typewriter extends ActiveObject { 

    private JTextArea out; 
    private String in; 

    public Typewriter(String s, JTextArea output) { 

    in = s; 
    out = output; 
    start(); 

    } 

    public void run() { 

    synchronized(out) { 

     for(int i=0; i<in.length(); i++) { 

     out.append(in.substring(i,i+1)); 
     if(in.charAt(i) == '.') { 
      pause(30); 
     } else { 
      pause(200); 
     } 

     } 

    }  

    } 

} 

電流:

CODE: 新打字機( 「\ nHello」,輸出); 新型打字機(「\ nWorld」,輸出);

電流輸出

HW ol elr ldo 

所需的輸出

Hello 
World 

很顯然,我省略了大部分的代碼從打字機類。如果真的需要我可以發佈。 ActiveObject的javadoc可以在here找到。這就是我被教過的線程,我擔心這可能是問題所在。

編輯:

每下面我已經添加了同步(OUT)線,但我得到一個NullPointerException當我嘗試運行代碼的答案。

Exception in thread "main" java.lang.NullPointerException 
    at objectdraw.ActiveObject.<init>(ActiveObject.java:239) 
    at com.caldwellysr.TBA.Typewriter.<init>(Typewriter.java:11) 
    at com.caldwellysr.TBA.Client.initGame(Client.java:78) 
    at com.caldwellysr.TBA.Client.<init>(Client.java:66) 
    at com.caldwellysr.TBA.Client.main(Client.java:24) 

打字機第11行是構造函數的標題。 客戶端行78是我打電話給新的打字機(「測試」,輸出);其中輸出是JTextArea 客戶機行66是對具有打字機的initGame()的調用 客戶機行24是JFrame構造函數。

+0

是的,代碼是必需的。請張貼它。 – Abbas 2012-01-30 03:55:56

+0

好吧會做... – CaldwellYSR 2012-01-30 03:57:40

+0

聽起來像你可能想要使用某種FIFO任務隊列。 – 2012-01-30 03:59:51

回答

3

看起來ActiveObject繼承自Thread類,並且異步運行,因此您不會知道線程何時運行。創建2個ActiveObject實例時,2個for循環不一定會依次運行。你看到的結果是你的文本區域被2個線程同時更新。

編輯:

您可以用同步子句同步運行代碼:

synchronized(out){ 
    for(int i=0; i<in.length(); i++) { 
     out.append(in.substring(i,i+1)); 

     if(in.charAt(i) == '.') { 
      pause(30); 
     } 
     else { 
      pause(200); 
     } 
    }  
} 
+0

因此,獲得所需輸出的唯一方法是不使用ActiveObject? – CaldwellYSR 2012-01-30 04:47:19

+0

看看我添加的代碼,它將適用於從Thread類繼承的類或從Thread繼承的任何其他類。 – Abbas 2012-01-30 05:17:03

+0

我給了這個upvote,因爲它看起來像正確的答案,但我得到一個奇怪的nullpointerexception,所以我不知道它是否工作或不完全。當我把這部分弄清楚,並且可以判斷它是否會起作用時,我會標記出正確的答案。 – CaldwellYSR 2012-01-30 05:30:58

1

雖然我最後的答案是JavaScript的,但是,這個理論應該是相同的。對於你的案例來說,你可能不需要每次都創建一個新的對象。你只需要新建一個對象,然後每當你想在JTextArea中添加新的單詞時,就可以調用類中的函數來將新字符串附加到「in」字符串中。並且在類中創建一個時間函數以定期輸出「in」字符串中的新字符。

類似這樣的:

import objectdraw。*; //主動對象來自何處。
import javax.swing。JTextArea中;

public class Typewriter extends ActiveObject { 

    private JTextArea out; 
    private String in; 
    private int index; 

    public Typewriter(String s, JTextArea output) { 

    in = s; 
    index = 0; 
    out = output; 
    start(); 

    } 

    public void run() { 

    while (1) { 
     if (index < in.length) { 
      out.append(in.substring(index,index+1)); 
      index++; 
     } 

     pause(200); 
    }  
    } 

    public void add_string(String s) { 
     in += s; 
    } 

} 

然後,您可以撥打: 打字機TW =新的打字機( 「你好」); tw.add_string(「world」);

+0

你的'add_string'方法會改變'in'的ref,串。 – akf 2012-01-30 05:28:53

0

這是一個非常簡單的方法來做到這一點,如果你只是使用這段代碼,它應該有所幫助。您可以通過以毫秒爲單位更改時間變量來加快速度。

import javax.swing.JTextArea; 

public class TypeWriter { 

private static final long time = 100; 

public static void TypeWriterEffect(String s, JTextArea output) { 

    String[] words = s.split(""); 


    for (String word : words) 
    { 
     output.append(word); 

     try { 
     Thread.sleep(time); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    } 
    } 
} 

你會做什麼在另一類是這樣的:

static JTextArea textWindow; 
TypeWriter.TypeWriterEffect("This is a Type Writer effect", textWindow); 

現在唐的只是把我放變量,這只是告訴你什麼是輸入變量來使用,因此使用自己的已添加到JFrame或JPanel的JTextArea變量。

希望這會有所幫助:)