2012-01-30 64 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变量。

希望这会有所帮助:)