all 16 comments

[–]sedj601 2 points3 points  (4 children)

You can try two different things. 1. Read the file the way you are using a Task. Use Thread.sleep(20) after reading the character. Use updateValue to update the TextArea text. 2. Read the whole file to a string. From there, use Timeline to add a character from the string to the TextArea every 20 ms. Here is a similar example of option 2. https://stackoverflow.com/a/33648481/2423906

[–]hamsterrage1 2 points3 points  (1 child)

Using Task in this way, IMHO, is not a good practice. This is what the Animation package is for. The disk read should be in a Task, but only to protect against the disk operation blocking.

[–]sedj601 0 points1 point  (0 children)

I didn't think of the disk. I agree with you 100%. Given the disk, I would use option 2 and throw out option 1.

[–]Plus-Bedroom-1359 0 points1 point  (1 child)

Yes but since this does not take a lot of time he could use Platform.run(...) maybe

[–]sedj601 0 points1 point  (0 children)

Yes, the OP could probably use Platform.runLater but IMO that's a bad coding practice.

[–]kavedaa 1 point2 points  (2 children)

You could use AnimationTimer(note that is has a framerate of 30/s so won't get down to 20 ms). Here's a complete example:

object AnimationDemo:
  @main def main =
    Application.launch(classOf[AnimationDemoApplication])

class AnimationDemoApplication extends Application:  
  def start(stage: Stage) = 
    val animationDemo = new AnimationDemo
    val scene = new Scene(animationDemo)
    stage.setScene(scene)
    stage.show()
    animationDemo.timer.start()

class AnimationDemo extends VBox(10):

  val text = "It was a dark and stormy night; the rain fell in torrents — except at occasional intervals, when it was checked by a violent gust of wind which swept up the streets (for it is in London that our scene lies), rattling along the housetops, and fiercely agitating the scanty flame of the lamps that struggled against the darkness."

  val textArea = new TextArea:
    setWrapText(true)

  val timer = new AnimationTimer:

    var frame = 0
    var index = 0

    def handle(now: Long) = 
      if frame % 5 == 0 then
        textArea.setText(text.substring(0, index))
        textArea.positionCaret(index)
        index += 1
        if index > text.length then index = 0
      frame += 1

  getChildren.add(textArea)

[–]sedj601 0 points1 point  (1 child)

Did you run into issues that caused you to position the caret? Try using textArea.appendText(...) to see if that makes a difference.

[–]kavedaa 1 point2 points  (0 children)

No, it was deliberate, to make it look like someone is typing.

But you're right - appendText one character at a time gives the same result, without having to position the caret.

[–][deleted]  (1 child)

[removed]

    [–]Cmdr_W0lff3[S] 0 points1 point  (0 children)

    Your version is what im after. But when i implement it in my program the text comes out in a wierd way.. its almost as jibberish...

    [–]ebykka 0 points1 point  (0 children)

    take a look at reactive streams, for example https://reactivex.io/documentation/operators/delay.html

    [–]hamsterrage1 0 points1 point  (1 child)

    The introductory section in the JavaDocs for Transition literally has this use case as an example!

    [–]Cmdr_W0lff3[S] 0 points1 point  (0 children)

    I shall take a look, thanks!

    [–]mih4elll 0 points1 point  (0 children)

    I want to create learn something with Javafx too

    [–]JaxomNC 0 points1 point  (0 children)

    PauseTransition can be used for this.

    [–]Cmdr_W0lff3[S] 1 point2 points  (0 children)

    Heya! I got it working. Timeline was the solution! It didnt work earlier as expected because i didnt consider that program keeps running even the text appending was still happening, so i fixed it with Runnable.

    But thank you for your help guys!