JavaFX: Best way to update GridPane after row dele

2019-05-19 03:40发布

问题:

I am using a GridPane (inside a ScrollPane) as a table with user entries. Each row incorporates a username (Label), an icon depicting its state (ImageView) and two buttons, the second of which is used to delete the user entry. The two images below depict the scroll pane before and after the user entry deletion

UPDATE: Code sample below:

The obvious issue is that the GridPane items do not get automatically re-arranged and the deleted line still occupies space. Do I have to provide a method to manually make the re-arrangement or is there an easier way to go about it?

for (NonSudoUser nsuser : nonSudoUsers) { // the users I want to show in the gridpane
    // user row
    RowConstraints row = new RowConstraints(30);
    gridPaneNonSudoUsers.getRowConstraints().add(row);

    // code that adds username label, status icon, checkstatus button - irrelevant I think to our issue
    // adding delete user button now:
    Button btnDeleteUser = new Button("Delete User");
    btnDeleteUser.setId("btnDel"+username); // explained below
    // delete user in a seperate thread
    btnDeleteUser.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
        // confirmation dialog here - omitted for brevity               
            Task<Void> task = new Task<Void>() {
            @Override
                public Void call() throws Exception {
                    String username = ((Button) event.getSource()).getId();
                    LinuxCommand lc = new LinuxCommand("userdel", "-r", username);
                    lc.execute();
                    return null;
                    }
                };
                task.setOnFailed(new EventHandler<WorkerStateEvent>() {
                    public void handle(WorkerStateEvent t) {
                        System.out.println("FAILURE deleting  " + username);
                    }
                });
                task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                    public void handle(WorkerStateEvent t) {
                        Platform.runLater(new Task<Void>() {
                            @Override
                            public Void call() throws Exception {
                                ArrayList<Node> toErase = new ArrayList<Node>();
                                for (Node nodeToErase: gridPaneNonSudoUsers.getChildren()) {
                                    if (nodeToErase.getId().endsWith(username)) // explaind below
                                        toErase.add(nodeToErase);
                                }
                                gridPaneNonSudoUsers.getChildren().removeAll(toErase);                                  
                                return null;
                            }
                        });
                    }
                });
                executorUserDeletion.submit(task);

The line that checks weather an element id contains the username is to know which elements to delete (upon elements addition, I append the actual username. So the GridPane row containing e.g. testuser0 entry, is composed of elements with the following ids: lbltestuser0, imgtestuser0, btnCheckStatustestuser0, btnDeleteUsertestuser0. (just a heuristic to know which row to delete each time) LinuxCommand is a custom class that accepts vararg String in its constructor to run the respective command.

回答1:

you can use setVisible(false) and setManaged(false) both together applied to row elements that delete action is invoked on, yet it will cause grid-lines overlapping each other and causing it to have darker and darker grid line if many rows get deleted. but it wont create any problem unless if you are using it as GUI feature.