JavaFX 2: Tworzenie ScrollPane automatycznie przewija do krawędzi po dodaniu zawartości

Korzystając z JavaFX 2, mam podstawowy przykład aScrollPane który zawieraHBox zLabels. Chcę być w stanie dodaćLabel doHBoxi jednocześnie przewiń do prawej krawędziScrollPane więc nowo dodanyLabel jest widoczny. Moja obecna metoda używasetHvalue() aby ustawić pozycję przewijania igetHmax() aby uzyskać maksymalną dozwoloną odległość przewijania.

Problem polega na tym, że kiedy ustawiam pozycję przewijania za pomocągetHmax(), jest tak jakby został dodanyLabel nie jest obliczany wScrollPanelszerokość przewijania. Czy istnieje sposób na zaktualizowanie tej wewnętrznej szerokości przed próbąsetHvalue?

Zobacz ten prosty przykładowy kod, który pokazuje problem.

W szczególności zwróć uwagę naaddChatItem(String item) metoda, która zawiera logikę przewijania do krawędziScrollPane.

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

Oto obraz problemu, zauważ, jakScrollPane nie przewinął się do prawej krawędzi.

Edytować:

Wymyśliłem obejście, ale jest to dalekie od ideału. Moim rozwiązaniem jest uruchomienie timera, który będzie używałsetHvalue() po upływie wystarczającego czasuScrollPane odkryć prawdziwą szerokość jego treści. mójaddChatItem() metoda wygląda teraz tak:

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

Niestety, liczba 50 w tej metodzie musi być większa niż czas potrzebnyScrollPane aby zaktualizować szerokość wewnętrznej zawartości, a to wydaje się być dalekie od zagwarantowania.

questionAnswers(2)

yourAnswerToTheQuestion