简体   繁体   English

ScrollPane.setVvalue() 不更新 javafx 中的滚动条

[英]ScrollPane.setVvalue() does not update scrollbar in javafx

I have a program where I can insert something in a textfield and then after pressing the enter button, it will be displayed as a label in a VBox.我有一个程序,我可以在文本字段中插入一些内容,然后在按下回车按钮后,它将在 VBox 中显示为 label。 My layout looks like this: A tab with inside a borderpane with on the bottom a hbox containing a textfield and a button and at the top a scrollpane containing a vbox full of labels.我的布局看起来像这样:一个带有内部边框的选项卡,底部有一个包含文本字段和按钮的 hbox,顶部是一个包含一个充满标签的 vbox 的滚动窗格。 截屏

This is the code:这是代码:

        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);

And this is the Command.java class:这是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));
    }
}

The problem is that when I call the setVvalue(1.0) method of the scrollpane, this is not setting the scrollbar at the bottom.问题是当我调用滚动窗格的setVvalue(1.0)方法时,这不是在底部设置滚动条。
I have tried with using output.setContent(outputL) before output.setVvalue(1.0) but nothing changes.我曾尝试在output.setVvalue(1.0)之前使用output.setContent(outputL) ) 但没有任何变化。
Thanks for any help谢谢你的帮助

Generate a layout pass before setting the scroll value.在设置滚动值之前生成布局通道。 To generate a layout pass see:要生成布局通道,请参见:


// 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());

Why this works为什么这有效

When the layout pass occurs, the vValue of the scroll pane will change to keep the currently visible area displayed rather than the new area.当布局传递发生时,滚动窗格的vValue将更改以保持显示当前可见区域而不是新区域。 If you then set the vValue to the maximum value, it will change from the value calculated in the layout pass to the maximum value, scrolling the pane to the bottom of the visible content.如果您随后将vValue设置为最大值,它将从布局传递中计算的值更改为最大值,将窗格滚动到可见内容的底部。

Sample code示例代码

This is just a code snippet to demonstrate the approach, not an executable application.这只是演示该方法的代码片段,而不是可执行的应用程序。

I did test the approach with the example code in the original question, and it worked fine.我确实使用原始问题中的示例代码测试了该方法,并且效果很好。

public void start(Stage stage) {
    VBox content = new VBox();
    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());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM