title: JavaFX Marquee Animation
body: <p>You maybe have seen some apps that when the <code>String</code> in a tab can't be fully shown then it is animated and is going back and front so the user can see what String the tab contains.Android is doing that is settings when your phone display is not enough to show the the whole label.</p>
  
  <p>Below is a code to achieve it in <code>JavaFX</code> using <code>Service</code>,but it is not a good way.</p>
  
  <p><strong>The Question is:</strong>
  Here is how i can do it using Animation or another build in JavaFX class?</p>
  
  <p>Code:</p>
  
  <pre><code>import javafx.application.Platform;
  import javafx.concurrent.Service;
  import javafx.concurrent.Task;
  import javafx.scene.control.Label;
  import javafx.scene.paint.Color;
  import javafx.scene.text.Font;
  import javafx.scene.text.FontWeight;
  import tools.InfoTool;
  
  public class MoveTitleService extends Service&lt;Void&gt;{
      private String title;
      volatile boolean doAnimation;
      private int counter;
      public Label movingText = new Label("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt");
  
  
      /**
       *Constructor
      */
      public MoveTitleService() {
           movingText.setFont(Font.font("null",FontWeight.BOLD,14));
           movingText.setTextFill(Color.WHITE);   
  
           setOnSucceeded( s -&gt;{
               movingText.setText("");
           });
      }
  
      //Start the Service
      public void startTheService(String title) {
          this.title = title;
          doAnimation = true;
  
          restart();
      }
  
  
      //Stop the Service
      public void stopService(){
          doAnimation=false;
      }
  
      @Override
      protected Task&lt;Void&gt; createTask() {
          return new Task&lt;Void&gt;() {
              @Override
              protected Void call() throws Exception {
  
                  while (doAnimation) {
                      //System.out.println("MoveTitleService is Running...");
  
                      // One letter at a time
                      for (int m = 0; m &lt;= title.length(); m++) {
                          counter=m;
  
                          Platform.runLater( () -&gt;{
                              movingText.setText(title.substring(0, counter) + addSpaces(title.length() - counter));      
                          });
  
                          if(!doAnimation) break;
                          Thread.sleep(150);
                      }
  
                      // Disappearing to back
                      for (int m = 0; m &lt; title.length(); m++) {
                          counter=m;
  
                          Platform.runLater( () -&gt;{
                              movingText.setText(title.substring(counter));
                          });
  
                          if(!doAnimation) break;
                          Thread.sleep(150);
                      }
  
                      // Appearing to front
                      for (int m = 1; m &lt;= title.length(); m++) {
                          counter=m;
  
                          Platform.runLater( () -&gt;{
                              movingText.setText(title.substring(title.length() - counter));
                          });
  
                          if(!doAnimation) break;
                          Thread.sleep(150);
                      }
  
                      if(!doAnimation) break;
                      for(int i=0; i&lt;3000/150; i++)
                          Thread.sleep(150);
                      Thread.sleep(3000);
  
                  }
  
                  return null;
              }
  
              private String addSpaces(int spaces) {
                  String z = "";
                  for (int i = 0; i &lt;= spaces; i++)
                      z += " ";
  
                  return z;
              }
  
          };
      }
  
  }
  </code></pre>