使用JTextArea打字机效果

时间:2012-01-30 03:52:20

标签: java multithreading swing synchronization thread-safety

我已经设法制作了一个打字机课程,它可以完成我想要的任务。它将输出一次给出一个字符的字符串,在每个字符之间暂停,就好像它们被输入一样,在句点之后暂停一点。我现在遇到的问题是,当我使用这个类时,它只能工作一次。当我调用它两次(或更多)时,它会尝试同时运行它们。这会导致重大问题。所以我需要一种方法让这个类的第一个实例运行,然后每个实例在开始之前等待“它转”。以下是期望结果和当前的一个例子。

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”,输出);

CURRENT OUTPUT

HW ol elr ldo

期望的输出

Hello
World

显然我遗漏了Typewriter类中的大部分代码。如果那真的需要我可以发布它。可以找到ActiveObject的javadoc here。这就是我教授线程的方式,我担心这可能是问题所在。

编辑:

根据下面的答案,我添加了synchronized(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)

Typewriter第11行是构造函数的标题。 客户线78是我称之为新打字机(“测试”,输出)的地方;其中output是JTextArea 客户端行66是对initGame()的调用,其中包含打字机 客户端第24行是JFrame构造函数。

3 个答案:

答案 0 :(得分:3)

似乎ActiveObject继承自Thread类并以异步方式运行,因此您不知道线程何时运行。当您创建2个ActiveObject个实例时,2个for循环不一定会一个接一个地运行。您看到的结果是您的文本区域同时由2个线程更新。

修改

您可以使用synchronized子句同步运行代码:

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);
        }
    }      
}

答案 1 :(得分:1)

虽然我的最后一个答案是针对javascript,但理论应该是相同的。对于您的工作情况,您可能不需要每次都创建一个新对象。您只需要新建一个对象,然后每次要在JTextArea中添加新单词时,您只需调用类中的函数将新字符串附加到“in”字符串即可。并在类中创建一个时间函数,以便在“in”字符串中定期输出新的char。

这样的事情:

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( “世界”);

答案 2 :(得分: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变量。

希望这会有所帮助:)