首页 > 解决方案 > 发生文件写入后如何在 JavaFX 中自动更新 TabPane 选项卡?

问题描述

我正在编写一个程序来存储有关企业客户的信息。

我创建了按钮功能成员来添加新客户端,它工作正常。

但是,我将 TabPane 合并到我的主要 JavaFX BorderPane 的顶部,并且在写入该文件后自动更新选项卡时遇到问题,为此它会将新添加的客户端显示到选项卡列表中。

如果我关闭程序并重新打开它会显示所有信息,但我想在单击提交按钮后立即更新选项卡。

我曾尝试在应用程序扩展应用程序类中使用 TabPane,但是我无法从我的菜单类中访问它。继承 Application 类的重写 start 方法对于 JavaFX 来说是相当令人头疼的。

然后,我尝试将 TabPane 移动到它自己的类文件中,我意识到我不知道如何强制标签从主 App 扩展 Application 类更新......

我该如何解决?

这是我的主要应用程序类:

public class App extends Application {
//User screen size
private Rectangle2D screenSize = Screen.getPrimary().getBounds();

//Main window and sub windows
private BorderPane mainWindow = new BorderPane();
private GridPane buttonTabPane = new GridPane();
private Menus menu = new Menus();

//Button bar
private ButtonBar buttonBar = new ButtonBar();
private Button newClient = new Button("New Client");
private Button editClient = new Button("Edit Client");
private Button findClient = new Button("Find Client");

//Client tabs
private Tabs clientTabs = new Tabs();
private TabPane clientTabPane = clientTabs.getTabPane();

//Padding
private Insets pad = new Insets(10);

@Override
public void start(Stage stage) {
    stage.setTitle("Cybernetic Tax Automation");

    //Button bar
    buttonBar.getButtons().addAll(newClient,editClient,findClient);
    buttonBar.setPadding(pad);

    //Button actions
    newClient.setOnAction(e -> {
        mainWindow.setCenter(menu.newClient());
    });

    //Combo pane for button bar and tabs
    buttonTabPane.setConstraints(buttonBar,0,0);
    buttonTabPane.setConstraints(clientTabs.getTabPane(),0,1);
    buttonTabPane.getChildren().addAll(buttonBar,clientTabs.getTabPane());

    //Find currently selected client tab
    clientTabs.getTabPane().getSelectionModel().selectedItemProperty().addListener(e -> {
        System.out.println(clientTabs.getTabPane().getSelectionModel().getSelectedItem().getText());
    });

    //Main window
    mainWindow.setTop(buttonTabPane);
    Scene scene = new Scene(mainWindow,screenSize.getMaxX(),screenSize.getMaxY());
    stage.setScene(scene);
    stage.show();
}

}

这是指向新客户端按钮窗口的菜单类:

public class Menus {
//Menus
private GridPane gridPane = new GridPane();

//System specific home
private String home = System.getProperty("user.home");

//File paths
private String clientsFilePath = "/Desktop/Clients.txt";

//Files
private Files fileIO = new Files();
private File clientsFile = new File(home + clientsFilePath);

//Padding and gaps
private Insets pad = new Insets(10,10,10,10);
private int gap = 10;

public GridPane newClient() {
    gridPane.setPadding(pad);
    gridPane.setHgap(gap);
    gridPane.setVgap(gap);

    Label firstName = new Label("First Name:");
    TextField firstNameField = new TextField();
    gridPane.setConstraints(firstName,0,0);
    gridPane.setConstraints(firstNameField,1,0);

    Label middleName = new Label("Middle Name:");
    TextField middleNameField = new TextField();
    gridPane.setConstraints(middleName,0,1);
    gridPane.setConstraints(middleNameField,1,1);

    Label lastName = new Label("Last Name:");
    TextField lastNameField = new TextField();
    gridPane.setConstraints(lastName,0,2);
    gridPane.setConstraints(lastNameField,1,2);

    Button submit = new Button("Submit");
    gridPane.setConstraints(submit,1,3);
    submit.setOnAction(e -> {
        String fullName = "";

        for(Node node : gridPane.getChildren()) {
            if(node instanceof TextField) {
                String firstLetter = ((TextField)node).getText().substring(0,1).toUpperCase();
                String upperName = firstLetter + ((TextField)node).getText().substring(1);
                fullName += upperName + " ";
            }
        }

        fullName += "\n";

        fileIO.writeFile(clientsFile,fullName);
        firstNameField.clear();
        middleNameField.clear();
        lastNameField.clear();
    });

    gridPane.getChildren().addAll(
            firstName,
            firstNameField,
            middleName,
            middleNameField,
            lastName,
            lastNameField,
            submit
    );

    return gridPane;
}

}

这是我最近创建的 Tabs 类:

public class Tabs {
//System specific home
private String home = System.getProperty("user.home");

//File paths
private String clientsFilePath = "/Desktop/Clients.txt";

//Files
private File clientsFile = new File(home + clientsFilePath);

//Objects
private TabPane tabPane = new TabPane();
private Files fileIO = new Files();

public Tabs() {
    tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
    tabPane.setTabMinWidth(120);

    updateTabs();
}

public TabPane getTabPane() {
    return tabPane;
}

public void updateTabs() {
    ArrayList<String> clientList = fileIO.readFile(clientsFile);
    tabPane.getTabs().removeAll();

    for(int i = 0; i < clientList.size(); i++) {
        Tab client = new Tab(clientList.get(i));
        tabPane.getTabs().add(client);
    }
}

}

标签: javafx

解决方案


我相信还有其他有效的方法可以解决这个问题,下面是我现在可以快速想到的方法。

您可以将 Tabs 实例传递给 newClient() 方法,并在文件写入完成时请求更新选项卡。

所以像...

在您的 start() 方法中:

newClient.setOnAction(e -> {
   mainWindow.setCenter(menu.newClient(clientTabs));
});

在 newClient 方法中:

// PASS THE Tabs INSTANCE TO THIS METHOD    
public GridPane newClient(Tabs clientTabs) {
        gridPane.setPadding(pad);
        ...
        ...
        submit.setOnAction(e -> {
            String fullName = "";

            for(Node node : gridPane.getChildren()) {
                if(node instanceof TextField) {
                    String firstLetter = ((TextField)node).getText().substring(0,1).toUpperCase();
                    String upperName = firstLetter + ((TextField)node).getText().substring(1);
                    fullName += upperName + " ";
                }
            }

            fullName += "\n";

            fileIO.writeFile(clientsFile,fullName);
            firstNameField.clear();
            middleNameField.clear();
            lastNameField.clear();
            // CALL THE UPDATE TABS WHEN THE FILE WRITING IS DONE
            clientTabs.updateTabs();
        });
        ...
    }

推荐阅读