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
vonLabel
s. Ich möchte eine hinzufügen könnenLabel
zumHBox
und 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.