Эффект пишущей машинки с помощью JTextArea - PullRequest
4 голосов
/ 30 января 2012

Мне удалось создать класс пишущей машинки, который по большей части выполняет то, что я хочу.Он будет выводить строку, переданную ему по одному символу за раз, делая паузу между ними, как если бы они были напечатаны, делая паузу немного дольше после периодов.У меня сейчас проблема в том, что когда я использую этот класс, он работает только один раз.Когда я вызываю его дважды (или больше), он пытается запустить их одновременно.Это вызывает серьезные проблемы.Поэтому мне нужен способ запуска первого экземпляра этого класса и каждого последующего, чтобы дождаться «своей очереди» перед запуском.Ниже приведен пример желаемого результата и текущего.

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

      }

    }      

  }

}

Текущий:

КОД: новая пишущая машинка ("\ nHello", вывод);новая пишущая машинка ("\ nWorld", вывод);

ТЕКУЩИЙ ВЫХОД

HW ol elr ldo

ЖЕЛАЕМЫЙ ВЫХОД

Hello
World

Очевидно, я пропустил большую часть кода из пишущей машинкиучебный класс.Если это действительно нужно, я могу опубликовать это.Javadocs для ActiveObject можно найти здесь .Вот как меня учили потокам, и я боюсь, что это может быть проблемой.

РЕДАКТИРОВАТЬ:

В ответ ниже я добавил синхронизированную (вне) строку, но яполучить нулевое исключение исключения при попытке запустить код.

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 - это то, где я вызываю новую пишущую машинку («Тестирование», вывод);где output - строка клиента JTextArea 66 - это вызов initGame (), в котором есть пишущая машинка, строка клиента 24 - это конструктор JFrame.

Ответы [ 3 ]

3 голосов
/ 30 января 2012

Кажется, что ActiveObject наследуется от класса Thread и работает асинхронно, поэтому вы не будете знать, когда будет запущен ваш поток. Когда вы создаете 2 ActiveObject экземпляра, циклы 2 for не обязательно будут запускаться один за другим. В результате вы видите, что ваша текстовая область обновляется двумя потоками одновременно.

EDIT:

Вы можете запустить ваш код синхронно с помощью оператора 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 голос
/ 30 января 2012

Хотя мой последний ответ был для javascript, теория должна быть такой же. Чтобы ваш случай работал, вам, вероятно, не нужно каждый раз создавать новый объект. Вам просто нужно создать новый объект один раз, а затем каждый раз, когда вы хотите поместить новые слова в JTextArea, вы можете просто вызвать функцию в классе, чтобы добавить новую строку в строку «in». И создайте в классе функцию времени для периодического вывода нового символа в строке «in».

Примерно так:

импорт 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 = новая пишущая машинка («Hello»); tw.add_string ( "мир");

0 голосов
/ 05 февраля 2014

Вот очень простой способ сделать это, если вы просто используете этот код, и он должен помочь. Вы можете ускорить его, изменив переменную времени в миллисекундах.

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

Теперь просто поместите переменную, которую я поставил, просто чтобы показать вам, какой тип переменной использовать, поэтому используйте вашу собственную переменную JTextArea, которую вы добавили в JFrame или JPanel.

Надеюсь, это поможет:)

...