JavaFX 2: Wenn Sie ein ScrollPane erstellen, wird nach dem Hinzufügen von Inhalten automatisch ein Bildlauf zum Rand ausgeführt

Unter Verwendung von JavaFX 2 habe ich ein grundlegendes Beispiel für eineScrollPane das enthält eineHBox vonLabels. Ich möchte eine hinzufügen könnenLabel zumHBoxund blättern Sie gleichzeitig zum rechten Rand des FenstersScrollPane damit die neu hinzugekommenenLabel ist sichtbar. Meine derzeitige Methode verwendet diesetHvalue() zum Einstellen der Bildlaufposition undgetHmax() um die maximal zulässige Bildlaufentfernung zu erhalten.

Das Problem ist, dass ich beim Einstellen der Bildlaufposition mitgetHmax(), es ist als ob das gerade hinzugekommen istLabel wird in der nicht berechnetScrollPanel's Scrollbreite. Gibt es eine Möglichkeit, diese innere Breite zu aktualisieren, bevor ich es versuche?setHvalue?

Bitte sehen Sie sich diesen einfachen Beispielcode an, der das Problem aufzeigt.

Bitte beachten Sie insbesondere dieaddChatItem(String item) Methode, die die Logik zum Scrollen an den Rand des enthältScrollPane.

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

Hier ist ein Bild des Problems, beachten Sie, wie dieScrollPane hat nicht zum rechten Rand gescrollt.

Bearbeiten:

Ich habe eine Problemumgehung gefunden, die jedoch alles andere als ideal ist. Meine Lösung besteht darin, einen Timer zu starten, der verwendet wirdsetHvalue() nachdem genug zeit vergangen ist für dieScrollPane die wahre Breite seines Inhalts zu entdecken. meineaddChatItem() Methode sieht jetzt so aus:

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

Leider muss die Zahl 50 in dieser Methode größer sein als die dafür benötigte ZeitScrollPane die Breite seines inneren Inhalts zu aktualisieren, und das scheint alles andere als garantiert zu sein.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage