【问题标题】:JavaFX: Layout changing after loading fileJavaFX:加载文件后更改布局
【发布时间】:2019-08-20 07:33:16
【问题描述】:

以下问题:

我有一个带有TableView 的 GUI 来显示一些数据。

为避免在将新文件加载到表中时出现一些问题,我调用了一个方法来清除表中的所有数据(此事件发生在我从 FileChooser 中选择一个文件之后并且在数据显示之前) .

问题是,加载文件后,布局发生变化。

我发现发生这种情况是因为我正在清除 TableView 属性,但我不知道如何解决这个问题并且找不到解决方案。

可运行示例

public class GuiLayout extends Application {

    private Scene mainScene;
    private Stage mainStage;
    private Label filename;
    private VBox mainBox;

    private TableView tableView = new TableView();

    private FileChooser fileChooser;
    private Button save;
    private Button neu;
    private Button settings;
    private Button table;
    private Button row;
    private Button column;
    private Button date;

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        initButton();

        mainStage = new Stage();
        filename = new Label("Nr. 100 - Test Data (Applikation: TEST)");
        mainScene = new Scene(mainVBox(), 1200, 600);

        tableView.prefWidthProperty().bind(mainBox.widthProperty());
        tableView.prefHeightProperty().bind(mainBox.heightProperty());

        mainStage.setScene(mainScene);
        mainStage.show();
    }

    private GridPane mainGrid() {

        GridPane gridPane = new GridPane();
        gridPane.setVgap(10);
        gridPane.setHgap(10);

        gridPane.add(filename, 0, 0);
        gridPane.add(buttonBox(), 0, 1);
        gridPane.add(tableView, 0, 2);

        return gridPane;
    }

    private VBox buttonBox() {

        VBox buttonBox = new VBox();

        HBox firstRowBox = new HBox();
        HBox secRowBox = new HBox();

        firstRowBox.getChildren().addAll(fileChooserFile(), save, neu, settings);
        firstRowBox.setSpacing(5);
        secRowBox.getChildren().addAll(table, row, column, date);
        secRowBox.setSpacing(5);

        buttonBox.getChildren().addAll(firstRowBox, secRowBox);
        buttonBox.setSpacing(5);
        buttonBox.prefWidthProperty().bind(mainBox.widthProperty());

        return buttonBox;
    }

    private VBox mainVBox() {

        mainBox = new VBox();

        mainBox.prefWidthProperty().bind(mainStage.widthProperty().multiply(0.8));

        mainBox.setPadding(new Insets(10, 10, 10 ,10));
        mainBox.getChildren().add(mainGrid());

        return mainBox;
    }

    private void initButton() {

        fileChooser = new FileChooser();

        save = new Button("Save");
        save.setPrefWidth(100);
        neu = new Button("New");
        neu.setPrefWidth(100);
        settings = new Button("Settings");
        settings.setPrefWidth(100);
        table = new Button("Table");
        table.setPrefWidth(100);
        row = new Button("Row");
        row.setPrefWidth(100);
        column = new Button("Column");
        column.setPrefWidth(100);
        date = new Button("Date");
        date.setPrefWidth(100);
    }

    private Node fileChooserFile() {

        FileChooser.ExtensionFilter extFilter = new ExtensionFilter("Text File (*.txt)", "*.txt");
        fileChooser.getExtensionFilters().add(extFilter);

        final Button open = new Button("Open");
        open.setPrefWidth(100);
        open.setOnAction(ae -> openFileAction());

        return open;
    }

    private void openFileAction() {

        File input = fileChooser.showOpenDialog(mainStage);

        if (input != null) {

            try {

                String path = input.getParent();
                String fileName = input.getName();
                fileChooser.setInitialDirectory(new File(path));

                clearData();

            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void clearData() {

        tableView.getItems().clear();
        tableView.getColumns().clear();
        tableView.getStylesheets().clear();
        tableView.getProperties().clear();
        tableView.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
        tableView.getSortOrder().clear();
    }
}

感谢您的帮助!

【问题讨论】:

  • 删除tableView.getProperties().clear() 方法内的clearData() 行可修复错误。
  • @MayurPatel 我知道这会“解决”这个问题。但我需要tableView.getProperties().clear() 行来确保每个文件都像它应该的那样。
  • Node#getProperties() 返回的地图是 GridPane 等布局存储特定于 Node 的约束的位置。如果您清除该地图,那么约束就会消失。为什么你认为你需要清除那张地图?
  • @Slaw 每个文件都是独立的。行、列和宽度等的大小。为了确保文件正确加载(大小),我认为清除数据是最好的方法。
  • 您是否在不清除属性映射的情况下测试了您的应用程序?不清地图真的会出问题吗?

标签: java javafx tableview


【解决方案1】:

用于GridPane 的行和列索引存储在子节点的properties 映射中。如果GridPaneproperties 映射中找不到指定索引的条目,它会将此节点视为您为将其移动到左上角单元格的那些索引指定了0

请注意,重置您的代码甚至没有修改的属性是没有意义的。目前,您的clearData 方法中的所有内容都可以这么说(甚至清除items 列表),但让我们逐行查看该方法中的语句:

tableView.getItems().clear();

你可能会保留这条线。但是对于您当前的代码,您不会看到任何差异,因为您没有向 TableView 添加任何项目。

tableView.getColumns().clear();

这可能是必要的,也可能不是必要的。如果您只显示一种类型的数据并且没有对显示的列进行任何修改,那么您可能不需要这个。如果您想重置用户对列的重新排序,它也可能很有用。

tableView.getStylesheets().clear();

您没有向TableView 添加任何样式表。除非您打算动态执行此操作,否则此语句是不必要的:它对 GUI 没有任何影响。 (请确保不要一遍又一遍地添加相同的样式表。)

tableView.getProperties().clear();

仅当您将自己的数据存储在此地图中时才需要这样做。不过,您的代码中没有任何迹象表明这一点。如果您想使用地图存储一些数据,我强烈建议您使用Map.remove(Object key) 方法来清除您正在使用的那些键。如果你坚持清空整个地图,你需要确保其中存储的布局属性被重新分配,例如

tableView.getProperties().clear();
GridPane.setRowIndex(tableView, 2);
GridPane.setColumnIndex(tableView, 0);

tableView.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);

这样做没有任何意义,除非你指定了一些不同于默认值的值。

tableView.getSortOrder().clear();

可能需要重置任何已完成的排序,但如果您仍然清除列,则可以删除此语句。

【讨论】:

  • 感谢您的回答,它有效。就像@Slaw 所说,我可能可以删除我正在清除属性的行。我发布的代码只是我的问题的一个小例子,而不是我的主程序。对于我的主程序,这些行(期望清除属性)是必要的,因为我有单独数量的行和列(用户可以根据需要添加更多)。我的表格视图也有一个样式表,但我想我会一遍又一遍地添加它,所以我正在纠正这个问题。对于 ResizePolicy,我需要在加载新文件后修复列的大小调整。
猜你喜欢
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
相关资源
最近更新 更多