ScrollPane 未按需显示,FlowPane 内容
ScrollPane not showing as needed, FlowPane content
我在使用 JavaFX 8 中的 ScrollPane 根据需要显示滚动条时遇到了一些困难。我目前正在做的只是创建一个包含 x 个元素的 FlowPane,并将其设置为 ScrollPane 的内容。
当我垂直于 FlowPane 的方向缩小时出现问题。当元素开始换行并越界时,滚动条不会出现。当我平行于方向收缩时,这不会发生。我有一个小的 Java 程序来举例说明这个问题。
Start
Shrinking Parallel
Shrinking Perpendicular
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane();
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
scroll.setStyle("-fx-border-color: green");
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for(int i = 0; i < panes; i++) {
StackPane filler = new StackPane();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}
看看下面的代码,告诉我这是否是您想要实现的。我仍然不确定是什么导致了这个问题,我将不得不查看 ScrollPane 的文档来找出答案。我怀疑是 setFitToWidth
& setFitToHeight
方法。虽然我仍然相信这不是一个错误。
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane();
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
scroll.setStyle("-fx-border-color: green");
// Apparently this cause the issue here.
// scroll.setFitToHeight(true);
// scroll.setFitToWidth(true);
// Instead just make the flow pane take the dimensions of the ScrollPane
// the -5 is to not show the Bars when both of panes have the same dimensions
flow.prefWidthProperty().bind(Bindings.add(-5, scroll.widthProperty()));
flow.prefHeightProperty().bind(Bindings.add(-5, scroll.heightProperty()));
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for (int i = 0; i < panes; i++) {
HBox filler = new HBox();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}
查看 ScrollPane 的文档,特别是 setFitToHeight
您会发现:
Property description:
If true and if the contained node is a
Resizable, then the node will be kept resized to match the height of
the ScrollPane's viewport. If the contained node is not a Resizable,
this value is ignored.
并且由于 ScrollPane 内的节点将保持调整大小以匹配 ScrollPane 视口的宽度和高度,这就是 Vertical ScrollBar 永远不会出现的原因。
您可以添加以下代码以始终显示垂直滚动条。
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
当计算出 ScrollPane 内 FlowPane 所需的高度时,将传递宽度值 -1。当所有内容都适合一行时,流程窗格将报告所需的高度。
在这种情况下,作为解决方法,您可以传递上次布局计算的宽度。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane() {
@Override protected double computeMinHeight(double width) {
double minHeight = super.computeMinHeight(width != -1 ? width :
/* When no width is specified, use the current contol size*/
getWidth());
return minHeight;
}
};
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
flow.maxWidthProperty().bind(scroll.widthProperty());
scroll.widthProperty().addListener((observable, oldValue, newValue)->{
/* clearSizeCache */
flow.requestLayout();
});
scroll.setStyle("-fx-border-color: green");
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for(int i = 0; i < panes; i++) {
StackPane filler = new StackPane();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}
我在使用 JavaFX 8 中的 ScrollPane 根据需要显示滚动条时遇到了一些困难。我目前正在做的只是创建一个包含 x 个元素的 FlowPane,并将其设置为 ScrollPane 的内容。
当我垂直于 FlowPane 的方向缩小时出现问题。当元素开始换行并越界时,滚动条不会出现。当我平行于方向收缩时,这不会发生。我有一个小的 Java 程序来举例说明这个问题。
Start
Shrinking Parallel
Shrinking Perpendicular
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane();
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
scroll.setStyle("-fx-border-color: green");
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for(int i = 0; i < panes; i++) {
StackPane filler = new StackPane();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}
看看下面的代码,告诉我这是否是您想要实现的。我仍然不确定是什么导致了这个问题,我将不得不查看 ScrollPane 的文档来找出答案。我怀疑是 setFitToWidth
& setFitToHeight
方法。虽然我仍然相信这不是一个错误。
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane();
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
scroll.setStyle("-fx-border-color: green");
// Apparently this cause the issue here.
// scroll.setFitToHeight(true);
// scroll.setFitToWidth(true);
// Instead just make the flow pane take the dimensions of the ScrollPane
// the -5 is to not show the Bars when both of panes have the same dimensions
flow.prefWidthProperty().bind(Bindings.add(-5, scroll.widthProperty()));
flow.prefHeightProperty().bind(Bindings.add(-5, scroll.heightProperty()));
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for (int i = 0; i < panes; i++) {
HBox filler = new HBox();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}
查看 ScrollPane 的文档,特别是 setFitToHeight
您会发现:
Property description: If true and if the contained node is a Resizable, then the node will be kept resized to match the height of the ScrollPane's viewport. If the contained node is not a Resizable, this value is ignored.
并且由于 ScrollPane 内的节点将保持调整大小以匹配 ScrollPane 视口的宽度和高度,这就是 Vertical ScrollBar 永远不会出现的原因。
您可以添加以下代码以始终显示垂直滚动条。
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
当计算出 ScrollPane 内 FlowPane 所需的高度时,将传递宽度值 -1。当所有内容都适合一行时,流程窗格将报告所需的高度。
在这种情况下,作为解决方法,您可以传递上次布局计算的宽度。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane flow = new FlowPane() {
@Override protected double computeMinHeight(double width) {
double minHeight = super.computeMinHeight(width != -1 ? width :
/* When no width is specified, use the current contol size*/
getWidth());
return minHeight;
}
};
flow.setStyle("-fx-border-color: red");
addPanes(flow, 16);
ScrollPane scroll = new ScrollPane(flow);
flow.maxWidthProperty().bind(scroll.widthProperty());
scroll.widthProperty().addListener((observable, oldValue, newValue)->{
/* clearSizeCache */
flow.requestLayout();
});
scroll.setStyle("-fx-border-color: green");
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
Scene scene = new Scene(scroll, 450, 450);
primaryStage.setScene(scene);
primaryStage.show();
}
public void addPanes(FlowPane root, int panes) {
for(int i = 0; i < panes; i++) {
StackPane filler = new StackPane();
filler.setStyle("-fx-border-color: black");
filler.setPrefSize(100, 100);
root.getChildren().add(filler);
}
}
}