问题
So the main issue what i have is when clicking on a ScrollBar Button. The Viewport of the Scrollpane changes, but not the children (Node) of the pane. I have either to request the focus on the pane or click on the icon in the taskmenu, that the Viewport content get's refreshed. Swing does this automatically when you move the scrollbars.
Is there another way to get this functionality working as described above and by code? The call requestFocus() seems strange to me. By the way: it highlights everytime that bothers.
Here is what i got so far:
public class ScrollPaneTest extends Application {
private ScrollPane scrollPane;
private StackPane stackPane;
private Pane pane;
private Button button;
@Override
public void start(Stage primaryStage) throws Exception {
scrollPane = new ScrollPane();
stackPane = new StackPane();
pane = new Pane();
button = new Button();
scrollPane.setPrefHeight(400.0);
scrollPane.setPrefWidth(600.0);
stackPane.setPrefHeight(1000.0);
stackPane.setPrefWidth(1000.0);
pane.setPrefHeight(200.0);
pane.setPrefWidth(200.0);
button.setMnemonicParsing(false);
button.setText("Button");
pane.getChildren().add(button);
stackPane.getChildren().add(pane);
scrollPane.setContent(stackPane);
scrollPane.viewportBoundsProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
Bounds oldViewportBounds = (Bounds) oldValue;
Bounds newViewportBounds = (Bounds) newValue;
double x = newViewportBounds.getMinX() * -1;
double y = newViewportBounds.getMinY() * -1;
button.setLayoutX(x);
button.setLayoutY(y);
// Working if focus is requested ...
//pane.requestFocus();
// ... or when clicked on the application icon in the taskmenu of windows
// Doesn't work
//pane.requestLayout();
}
});
VBox vbox = new VBox();
vbox.setPrefHeight(400.0);
vbox.setPrefWidth(600.0);
vbox.getChildren().add(scrollPane);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
} }
For illustration purposes:
Scrollbar button not pressed
Scrollbar button pressed twice
回答1:
Thanks Stackoverflow for this great article: JavaFX ScrollPane update viewportBounds on scroll
With that i was able to found the solution i needed. See below:
public class ScrollPaneTest extends Application {
private ScrollPane scrollPane;
private StackPane stackPane;
private Pane pane;
private Button button;
@Override
public void start(Stage primaryStage) throws Exception {
scrollPane = new ScrollPane();
stackPane = new StackPane();
pane = new Pane() {
@Override
protected void layoutChildren(){
super.layoutChildren();
// System.out.println("layout children");
// more ToDo's if neccessary...
}
};
// so that the Pane can be smaller than (potentionally) other Panes inside of the StackPane
pane.setManaged(false);
// set the dimension of the ScrollPane
pane.setPrefHeight(400.0);
pane.setPrefWidth(600.0);
button = new Button();
button.setLayoutX(25);
button.setLayoutY(25);
scrollPane.setPrefHeight(400.0);
scrollPane.setPrefWidth(600.0);
stackPane.setPrefHeight(1000.0);
stackPane.setPrefWidth(1000.0);
button.setMnemonicParsing(false);
button.setText("Button");
pane.getChildren().add(button);
stackPane.getChildren().add(pane);
scrollPane.setContent(stackPane);
scrollPane.hvalueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
//System.out.println("observable " + observable + " oldValue " + oldValue + " " + "newValue " + newValue);
double hmin = scrollPane.getHmin();
double hmax = scrollPane.getHmax();
double hvalue = scrollPane.getHvalue();
double contentWidth = scrollPane.getContent().getLayoutBounds().getWidth();
double viewportWidth = scrollPane.getViewportBounds().getWidth();
double hoffset =
Math.max(0, contentWidth - viewportWidth) * (hvalue - hmin) / (hmax - hmin);
pane.setLayoutX(hoffset);
pane.requestLayout();
}
});
scrollPane.vvalueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
//System.out.println("observable " + observable + " oldValue " + oldValue + " " + "newValue " + newValue);
double vmin = scrollPane.getVmin();
double vmax = scrollPane.getVmax();
double vvalue = scrollPane.getVvalue();
double contentHeight = scrollPane.getContent().getLayoutBounds().getHeight();
double viewportHeight = scrollPane.getViewportBounds().getHeight();
double voffset =
Math.max(0, contentHeight - viewportHeight) * (vvalue - vmin) / (vmax - vmin);
pane.setLayoutY(voffset);
pane.requestLayout();
}
});
VBox vbox = new VBox();
vbox.setPrefHeight(400.0);
vbox.setPrefWidth(600.0);
vbox.getChildren().add(scrollPane);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Unfortunately i wasn't able to upvote Mr. James_D's solution, but i try to link these both use cases.
Hope this one help others also. Cheers!
来源:https://stackoverflow.com/questions/50705926/javafx-scrollpane-with-stackpane-stackpanes-children-not-layouted-when-view