Typewriter Effect with JTextArea

I managed to create a typewriter class that does what I want, for the most part. It will output the string given to it one character at a time, pausing between them, as if they were printed, pausing a little longer after periods. The problem that I am facing right now is that when I use this class, it only works once. When I call it twice (or more), he tries to run them at the same time. This causes serious problems. Therefore, I need the first instance of this class to start, and each of them should wait for it to “turn” before starting. The following is an example of the desired result and current.

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

Current:

CODE: new typewriter ("\ nHello", exit); new typewriter ("\ nWorld", exit);

CURRENT EXIT

 HW ol elr ldo 

DESIRED EXIT

 Hello World 

Obviously, I left most of the code from the Typewriter class. If it is really necessary, I can publish it. Javadocs for an ActiveObject can be found here . This is how the threads taught me, and I'm afraid this might be a problem.

EDIT:

In response to below, I added a synchronized line (out), but when I try to run the code, I get a nullpointer exception.

 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) 

Writing line 11 is the heading for the constructor. Client line 78 is where I invoke a new typewriter ("Testing," output); where the output is JTextArea Client line 66 is a call to initGame (), in which there is a typewriter Client line 24 is a JFrame constructor.

+4
source share
3 answers

It seems that ActiveObject inherits from the Thread class and works asynchronously, so you don't know when the thread is executing. When you instantiate 2 ActiveObject , 2 for loops will not necessarily run one after the other. As a result, you see that your text area is updated by two streams at the same time.

EDIT:

You can run your code synchronously with a synchronous sentence:

 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); } } } 
+3
source

Although my last answer was for javascript, the theory should be the same. For the case when you are working, you probably do not need to create a new object every time. You just need to create a new object once, and then every time you want to put new words in JTextArea, you can just call a function in the class to add a new line to the "in" line. And create a time function in the class to periodically output the new char to the string "in".

Something like that:

import objectdraw. *; // Where the active object occurs.
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; } } 

Then you can call: Typewriter tw = new typewriter ("Hello"); tw.add_string ("world");

+1
source

Here is a very simple way to do this if you just use this code and it should help. You can speed it up by changing the temporary variable in milliseconds.

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

What would you do in another class is:

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

Now put it on only by putting the variable that I put, it's just to show you what type of variable to use, so use your own JTextArea variable that you added to the JFrame or JPanel.

Hope this helps :)

0
source

Source: https://habr.com/ru/post/1393685/


All Articles