ScrollPane.setVvalue() 不更新 javafx 中的滚动条
ScrollPane.setVvalue() does not update scrollbar in javafx
我有一个程序,我可以在文本字段中插入一些东西,然后在按下回车按钮后,它会在 VBox 中显示为标签。
我的布局如下所示:
一个带有边界窗格的选项卡,底部是一个包含文本字段和按钮的 hbox,顶部是一个包含充满标签的 vbox 的滚动窗格。
这是代码:
Tab consoleTab = new Tab("Console");
consoleTab.setClosable(false);
BorderPane consoleContent = new BorderPane();
TextField commandEntry = new TextField();
commandEntry.setPromptText("Enter command...");
Button exe = new Button("Enter");
HBox input = new HBox(5, commandEntry, exe);
VBox outputL = new VBox();
ScrollPane output = new ScrollPane();
output.setMinHeight(365);
output.setMaxHeight(365);
output.setContent(outputL);
EventHandler<ActionEvent> customEvent = e -> {
String in = commandEntry.getText();
if (in.equals("")) return;
Label inserted = new Label("> "+in);
inserted.setStyle("-fx-font-weight: bold");
outputL.getChildren().add(inserted);
commandEntry.setText("");
Command cmd = new Command(in, outputL);
cmd.execute(true);
output.setVvalue(1); // This does not work
};
commandEntry.setOnAction(customEvent);
exe.setOnAction(customEvent);
consoleContent.setTop(output);
consoleContent.setBottom(input);
consoleContent.setPadding(new Insets(5, 5, 5, 5));
consoleTab.setContent(consoleContent);
这是 Command.java
class:
public class Command {
private String command;
private VBox vbox;
public static final String NEW_FILE = "new_file";
public static final String OPEN_FILE = "open";
public static final String SAVE_FILE = "save";
public static final String LIST_FILES = "list";
public static final String HELP = "help";
public Command(String command, VBox v){
this.command = command;
this.vbox = v;
}
public void execute(boolean layout){
String[] args = this.command.split(" ");
String cmd = args[0];
String outputText = "";
switch (cmd){
case NEW_FILE:
break;
case OPEN_FILE:
outputText = "File opened";
break;
case SAVE_FILE:
break;
case LIST_FILES:
outputText = "Files listed";
break;
case HELP:
outputText = "Available commands:\nOPEN: open <file-name>\nLIST: list";
break;
default:
outputText = "Command not found, type help to get the list of available commands";
break;
}
if (layout){
makeLayout(outputText);
}
}
private void makeLayout(String outputText){
this.vbox.getChildren().add(new Label(outputText));
}
}
问题是当我调用滚动面板的setVvalue(1.0)
方法时,并没有在底部设置滚动条。
我曾尝试在 output.setVvalue(1.0)
之前使用 output.setContent(outputL)
但没有任何变化。
感谢您的帮助
在设置滚动值之前生成布局通道。要生成布局通道,请参阅:
- Get the height of a node in JavaFX (generate a layout pass)
// change the content of the scroll pane
// . . .
// generate a layout pass on the scroll pane.
scrollPane.applyCss();
scrollPane.layout();
// scroll to the bottom of the scroll pane.
scrollPane.setVvalue(scrollPane.getVmax());
为什么这样有效
发生布局传递时,滚动窗格的 vValue
将更改以保持显示当前可见区域而不是新区域。如果您随后将 vValue
设置为最大值,它将从布局传递中计算的值更改为最大值,将窗格滚动到可见内容的底部。
示例代码
这只是演示方法的代码片段,不是可执行的应用程序。
我确实使用原始问题中的示例代码测试了该方法,并且效果很好。
public void start(Stage stage) {
VBox content = new VBox();
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(content);
Button append = new Button("Append");
append.setOnAction(e -> appendToScrollPane(scrollPane));
VBox layout = new VBox(scrollPane, append);
stage.setScene(new Scene(layout));
stage.show();
}
public void appendToScrollPane(ScrollPane scrollPane) {
// ... actions which add content to the scroll pane ...
// generate a layout pass on the scroll pane.
scrollPane.applyCss();
scrollPane.layout();
// scroll to the bottom of the scroll pane.
scrollPane.setVvalue(scrollPane.getVmax());
}
我有一个程序,我可以在文本字段中插入一些东西,然后在按下回车按钮后,它会在 VBox 中显示为标签。
我的布局如下所示:
一个带有边界窗格的选项卡,底部是一个包含文本字段和按钮的 hbox,顶部是一个包含充满标签的 vbox 的滚动窗格。
这是代码:
Tab consoleTab = new Tab("Console");
consoleTab.setClosable(false);
BorderPane consoleContent = new BorderPane();
TextField commandEntry = new TextField();
commandEntry.setPromptText("Enter command...");
Button exe = new Button("Enter");
HBox input = new HBox(5, commandEntry, exe);
VBox outputL = new VBox();
ScrollPane output = new ScrollPane();
output.setMinHeight(365);
output.setMaxHeight(365);
output.setContent(outputL);
EventHandler<ActionEvent> customEvent = e -> {
String in = commandEntry.getText();
if (in.equals("")) return;
Label inserted = new Label("> "+in);
inserted.setStyle("-fx-font-weight: bold");
outputL.getChildren().add(inserted);
commandEntry.setText("");
Command cmd = new Command(in, outputL);
cmd.execute(true);
output.setVvalue(1); // This does not work
};
commandEntry.setOnAction(customEvent);
exe.setOnAction(customEvent);
consoleContent.setTop(output);
consoleContent.setBottom(input);
consoleContent.setPadding(new Insets(5, 5, 5, 5));
consoleTab.setContent(consoleContent);
这是 Command.java
class:
public class Command {
private String command;
private VBox vbox;
public static final String NEW_FILE = "new_file";
public static final String OPEN_FILE = "open";
public static final String SAVE_FILE = "save";
public static final String LIST_FILES = "list";
public static final String HELP = "help";
public Command(String command, VBox v){
this.command = command;
this.vbox = v;
}
public void execute(boolean layout){
String[] args = this.command.split(" ");
String cmd = args[0];
String outputText = "";
switch (cmd){
case NEW_FILE:
break;
case OPEN_FILE:
outputText = "File opened";
break;
case SAVE_FILE:
break;
case LIST_FILES:
outputText = "Files listed";
break;
case HELP:
outputText = "Available commands:\nOPEN: open <file-name>\nLIST: list";
break;
default:
outputText = "Command not found, type help to get the list of available commands";
break;
}
if (layout){
makeLayout(outputText);
}
}
private void makeLayout(String outputText){
this.vbox.getChildren().add(new Label(outputText));
}
}
问题是当我调用滚动面板的setVvalue(1.0)
方法时,并没有在底部设置滚动条。
我曾尝试在 output.setVvalue(1.0)
之前使用 output.setContent(outputL)
但没有任何变化。
感谢您的帮助
在设置滚动值之前生成布局通道。要生成布局通道,请参阅:
- Get the height of a node in JavaFX (generate a layout pass)
// change the content of the scroll pane
// . . .
// generate a layout pass on the scroll pane.
scrollPane.applyCss();
scrollPane.layout();
// scroll to the bottom of the scroll pane.
scrollPane.setVvalue(scrollPane.getVmax());
为什么这样有效
发生布局传递时,滚动窗格的 vValue
将更改以保持显示当前可见区域而不是新区域。如果您随后将 vValue
设置为最大值,它将从布局传递中计算的值更改为最大值,将窗格滚动到可见内容的底部。
示例代码
这只是演示方法的代码片段,不是可执行的应用程序。
我确实使用原始问题中的示例代码测试了该方法,并且效果很好。
public void start(Stage stage) {
VBox content = new VBox();
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(content);
Button append = new Button("Append");
append.setOnAction(e -> appendToScrollPane(scrollPane));
VBox layout = new VBox(scrollPane, append);
stage.setScene(new Scene(layout));
stage.show();
}
public void appendToScrollPane(ScrollPane scrollPane) {
// ... actions which add content to the scroll pane ...
// generate a layout pass on the scroll pane.
scrollPane.applyCss();
scrollPane.layout();
// scroll to the bottom of the scroll pane.
scrollPane.setVvalue(scrollPane.getVmax());
}