title: JavaFX 2: Making a ScrollPane automatically scroll to the edge after adding content
body: <p>Using JavaFX 2, I have a basic example of a <code>ScrollPane</code> that contains an <code>HBox</code> of <code>Label</code>s.  I want to be able to add a <code>Label</code> to the <code>HBox</code>, and simultaneously scroll to the right edge of the <code>ScrollPane</code> so that the newly added <code>Label</code> is visible.  My current method uses the <code>setHvalue()</code> to set the scroll position and <code>getHmax()</code> to get the maximum scrolling distance allowed.</p>
  
  <p>The problem is that when I set the scroll position using <code>getHmax()</code>, it is as if the just-added <code>Label</code> is not computed in the <code>ScrollPanel</code>'s scroll width.  Is there a way that I can update this inner width before trying <code>setHvalue</code>?</p>
  
  <p>Please see this simple example code which exhibits the issue.</p>
  
  <p>In particular, please notice the <code>addChatItem(String item)</code> method, which contains the logic for scrolling to the edge of the <code>ScrollPane</code>.</p>
  
  <pre><code>    import java.util.Timer;
      import java.util.TimerTask;
  
      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.ScrollPane;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.HBox;
      import javafx.scene.layout.StackPane;
      import javafx.scene.text.Font;
      import javafx.stage.Stage;
  
      public class ScrollPaneTest extends Application {   
          static int defaultFontSize = 30;
  
          ScrollPaneTest scrollPaneTest = this;
  
          ScrollPane chatBoxScrollPane = new ScrollPane();
          HBox chatBox = new HBox();
          Chatter chatter = new Chatter();
  
          public static void main(String[] args) {
              launch(args);//default
          }
  
          @Override
          public void stop() throws Exception {
              super.stop();
              System.exit(0);
          }
  
          @Override
          public void start(Stage primaryStage) {
              BorderPane borderPane = new BorderPane();       
  
              StackPane chatBoxStackPane = new StackPane();
  
              chatBoxScrollPane.setContent(chatBox);
              //chatBoxScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
              chatBoxScrollPane.setMaxHeight(50);
  
              chatBoxStackPane.getChildren().add(chatBoxScrollPane);
  
              borderPane.setCenter(chatBoxStackPane);
  
  
              Scene scene = new Scene(borderPane, 800, 600);
              primaryStage.setScene(scene);
              primaryStage.setTitle("Scroll Demo");
              primaryStage.show(); 
  
  
              new Thread("mainGameControlThread") {
                  public void run() {
                      chatter.chatLoop(scrollPaneTest);
                  }
              }.start();
          }
  
          public void addChatItem(String chatString) {
              Label title = new Label(chatString);        
              title.setFont(new Font("Verdana", defaultFontSize));
  
              chatBox.getChildren().add(title);
  
              chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax());
          }
  
          class Chatter {
              public void chatLoop(final ScrollPaneTest test) {
  
                  Timer closingCeremonyTimer = new Timer();
                  closingCeremonyTimer.schedule(new TimerTask() {
                      public void run() {
                          Platform.runLater(new Runnable() {
                              @Override 
                              public void run() {
                                  test.addChatItem("Hello World. ");
                              }
                          });
                          chatLoop(test);
                      }
                  }, (long) (0.5*1000));
              }
          }
      }
  </code></pre>
  
  <p>Here is an image of issue, notice how the <code>ScrollPane</code> has not scrolled to the right edge. </p>
  
  <p><img src="https://i.imgur.com/YBx3wfD.png" alt="image"></p>
  
  <p><strong><em>Edit:</em></strong></p>
  
  <p>I've come up with a workaround but it is very far from ideal.  My solution is to start a timer which will use <code>setHvalue()</code> after enough time has passed for the <code>ScrollPane</code> to discover the true width of its content.  my <code>addChatItem()</code> method now looks like this:</p>
  
  <pre><code>public void addChatItem(String chatString) {
      Label title = new Label(chatString);        
      title.setFont(new Font("Verdana", defaultFontSize));
  
      chatBox.getChildren().add(title);
  
      Timer closingCeremonyTimer = new Timer();       
      closingCeremonyTimer.schedule(new TimerTask() {
          public void run() {
              chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax());
          }
      }, (long) 50);
  }
  </code></pre>
  
  <p>Unfortunately, the number 50 in that method needs to be greater than the time that it takes the <code>ScrollPane</code> to update its inner content's width, and that seems to be far from guaranteed.</p>