JavaFX ScrollPane setVvalue() не работает должным образом
В моем приложении у меня есть ScrollPane с VBox, который может содержать от 0 до 1000 панелей с установленной высотой 90 в каждой. Каждая панель имеет связанные элементы, которые можно загрузить с кнопки внутри, которая очищает VBox и добавляет его дочерние элементы вместе с кнопкой "Возврат к результатам", которая загружает предыдущий список и должна вернуться в то же место в ScrollPane. Однако setVvalue(), похоже, не работает. Панели и их дети одного класса.
package application;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Main extends Application {
public VBox resultsBox;
public ScrollPane scroll;
public List<CustomClass> results = new ArrayList<CustomClass>();
public Button returnToResults;
public class CustomClass extends HBox {
public List<CustomClass> items;
public boolean hasItems() {
return items != null && !items.isEmpty();
}
public CustomClass(String text, boolean hasItems) {
setMinHeight(90);
setPrefHeight(90);
setMaxHeight(90);
setMaxWidth(Double.MAX_VALUE);
setAlignment(Pos.CENTER);
setStyle("-fx-border-color: red");
Button children = new Button("View Children "+text);
children.setDisable(!hasItems);
getChildren().add(children);
children.setOnAction(e -> {
viewChildren(this);
});
if(hasItems) {
items = new ArrayList<CustomClass>();
for(int i=0; i<10; i++) {
items.add(new CustomClass(text+"."+i, false));
}
}
}
}
public double vValue = 0.0;
public void viewChildren(CustomClass cc) {
Platform.runLater(() -> {
vValue = scroll.getVvalue();
System.out.println("0. "+vValue);
resultsBox.getChildren().clear();
resultsBox.getChildren().addAll(cc.items);
returnToResults.setDisable(false);
});
}
public void returnToResults() {
Platform.runLater(() -> {
resultsBox.getChildren().clear();
resultsBox.getChildren().addAll(results);
System.out.println("1. "+vValue+" "+scroll.getVvalue());
scroll.setVvalue(vValue);
System.out.println("2. "+vValue+" -> "+scroll.getVvalue()); // Sets correctly.
returnToResults.setDisable(true);
});
}
public void start(Stage stage) throws Exception {
resultsBox = new VBox(5);
resultsBox.setFillWidth(true);
resultsBox.setAlignment(Pos.TOP_CENTER);
scroll = new ScrollPane(resultsBox);
scroll.setMaxWidth(Double.MAX_VALUE);
scroll.setFitToWidth(true);
for(int i=0; i<100; i++) {
results.add(new CustomClass("#"+i, true));
}
resultsBox.getChildren().addAll(results);
returnToResults = new Button("Return to Results");
returnToResults.setStyle("-fx-base: green");
returnToResults.setDisable(true);
returnToResults.setOnAction(e -> {
returnToResults();
});
BorderPane root = new BorderPane();
root.setCenter(scroll);
root.setBottom(returnToResults);
Scene scene = new Scene(root,400,400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
SetVvalue () работает и возвращает ScrollPane к его старому значению при распечатке, но сама ScrollPane никуда не уходит и остается наверху. Связано ли это с удалением и добавлением узлов в VBox? Почему ScrollPane не перемещается при установке Vvalue?
2 ответа
Во время звонка scroll.setVvalue(vValue)
панель прокрутки не выполнила макет, так как его содержимое изменилось, и, следовательно, не "переизмерило" размер своего содержимого. Таким образом, полоса прокрутки "большой палец" перемещается путем интерпретации vvalue
в контексте предыдущего макета. Вы можете это исправить с помощью
public void returnToResults() {
Platform.runLater(() -> {
vbox.getChildren.clear();
vbox.getChildren.addAll(results);
scroll.layout();
scroll.setVvalue(vValue);
returnToResults.setDisable(true);
});
}
В сторону: эти методы вызываются из фонового потока? Почему их содержимое обернуто в Platform.runLater(...)
?
В моем случае зовет layout()
метод не сработал. Я также должен был позвонить applyCss()
на мою нынешнюю сцену.
Соответствующий FXML:
<ScrollPane fx:id="messageScrollPane" fitToWidth="true" fitToHeight="true">
VBox fx:id="messageBox"/>
</ScrollPane>
Я хотел, чтобы полоса прокрутки автоматически прокручивалась вниз, если я добавляю новую метку в
messageBox
Итак, мой метод для достижения этой цели заключается в следующем:
public void addMessage(String message) {
messageBox.getChildren().add(new Label(text));
currentScene.applyCss();
currentScene.layout();
messageScrollPane.setVvalue(1.0);
}
Надеюсь, это поможет кому-то.