在 javafx gridpane 中添加不可见的行

Add invisible row in javafx gridpane

我想在网格窗格中添加一个不可见的行。然后我想根据用户选择显示和隐藏它。我已经设法让一般功能正常工作,但问题是当行内容被隐藏时,会有一个额外的 space。我不确定这是实际行还是 vgap?无论如何,我想摆脱这个额外的 space。 这是我的网格窗格:

public class CustomGrid extends GridPane{

public CustomGrid() {
    this.setHgap(20);
    this.setVgap(20);

    ColumnConstraints firstColConstraints =  new ColumnConstraints();
    firstColConstraints.setHalignment(HPos.RIGHT);
    firstColConstraints.setPercentWidth(50.0);
    firstColConstraints.setHgrow(Priority.ALWAYS);
    ColumnConstraints secondColConstraints =  new ColumnConstraints();
    ColumnConstraints thirdColConstraints =  new ColumnConstraints();
    thirdColConstraints.setHgrow(Priority.ALWAYS);
    thirdColConstraints.setHalignment(HPos.LEFT);

    this.getColumnConstraints().addAll(firstColConstraints, secondColConstraints, thirdColConstraints);
    VBox.setMargin(this, new Insets(10, 0, 50, 0));

}

我添加了内容然后像这样隐藏它

Pane content = new Pane()
pane.setVisible(false);
pane.setManaged(false);
add(content, 0, 1);

当用户使其可见但当它隐藏时,行与行之间存在额外的间隙,我对此感到满意。谁能告诉我解决这个问题的方法。

谢谢。

如评论中所述():

隐藏时将高度更改为0。

我认为处理此问题的最佳方法是实际从网格窗格中删除该行,而不是尝试创建该行 "invisible"。在 GridPane 中的任意位置插入和删除行有点棘手,因为 GridPane API 本身不支持此类功能。因此,我根据您的自定义 GridPane 实现创建了一个小实用程序,它演示了在 GridPane 中添加和删除行。为此,自定义实现必须保留关于哪些节点位于哪些行的内部概念,并在添加或删除新行时更新每个节点和每个行的列约束。隐藏可以通过从网格窗格中删除一行,然后在稍后阶段将同一行添加回网格窗格中先前删除的索引处来完成。我知道这并不是您想要的,但对我来说这似乎是最合理的解决方案。

/** Click on a Label to remove the row containing the label from the GridPane */
import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.*;

public class HiddenNodes extends Application {

    private static final int N_COLS = 3;
    private static final int INIT_N_ROWS = 10;

    private int nextRowId = 0;
    private Node[] lastRemovedRow = null;

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

    @Override
    public void start(Stage stage) throws Exception {
        CustomGrid grid = new CustomGrid();

        for (int i = 0; i < INIT_N_ROWS; i++) {
            Label[] labels = createRow(grid);
            grid.insertRow(i, labels);
        }

        Button prepend = new Button("Prepend");
        prepend.setOnAction(event -> {
            Label[] labels = createRow(grid);
            grid.insertRow(0, labels);
        });

        Button append = new Button("Append");
        append.setOnAction(event -> {
            Label[] labels = createRow(grid);
            grid.insertRow(grid.getRowsSize(), labels);
        });

        HBox controls = new HBox(10, prepend, append);

        VBox layout = new VBox(10, controls, grid);
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout, 200, 600));
        stage.show();
    }

    private Label[] createRow(CustomGrid grid) {
        Label[] labels = new Label[N_COLS];
        for (int j = 0; j < N_COLS; j++) {
            final int fj = j;
            labels[j] = new Label(nextRowId + ":" + j);
            labels[j].setStyle("-fx-background-color: coral;");
            labels[j].setOnMouseClicked((MouseEvent e) -> {
                lastRemovedRow = grid.removeRowContaining(labels[fj]);
            });
        }

        nextRowId++;

        return labels;
    }

    class CustomGrid extends GridPane {
        private ObservableList<Node[]> rows = FXCollections.observableArrayList();

        CustomGrid() {
            this.setHgap(20);
            this.setVgap(20);

            ColumnConstraints firstColConstraints = new ColumnConstraints();
            firstColConstraints.setHalignment(HPos.RIGHT);
            firstColConstraints.setPercentWidth(50.0);
            firstColConstraints.setHgrow(Priority.ALWAYS);
            ColumnConstraints secondColConstraints = new ColumnConstraints();
            ColumnConstraints thirdColConstraints = new ColumnConstraints();
            thirdColConstraints.setHgrow(Priority.ALWAYS);
            thirdColConstraints.setHalignment(HPos.LEFT);

            this.getColumnConstraints().addAll(firstColConstraints, secondColConstraints, thirdColConstraints);
            VBox.setMargin(this, new Insets(10, 0, 50, 0));
        }

        void insertRow(int rowIdx, Node... nodes) {
            for (int i = rows.size() - 1; i >= rowIdx; i--) {
                for (int j = 0; j < rows.get(i).length; j++) {
                    setConstraints(rows.get(i)[j], j, i + 1);
                }
            }

            addRow(rowIdx, nodes);
            rows.add(rowIdx, nodes);
        }

        private Node[] removeRow(int rowIdx) {
            for (int i = rows.size() - 1; i > rowIdx; i--) {
                for (int j = 0; j < rows.get(i).length; j++) {
                    setConstraints(rows.get(i)[j], j, i - 1);
                }
            }

            for (Node node: rows.get(rowIdx)) {
                getChildren().remove(node);
            }
            return rows.remove(rowIdx);
        }

        Node[] removeRowContaining(Node node) {
            Iterator<Node[]> rowIterator = rows.iterator();
            int rowIdx = 0;
            while (rowIterator.hasNext()) {
                Node[] row = rowIterator.next();
                for (Node searchNode : row) {
                    if (searchNode == node) {
                        return removeRow(rowIdx);
                    }
                }

                rowIdx++;
            }

            return null;
        }

        int getRowsSize() {
            return rows.size();
        }
    }
}

以上程序只是一个大纲,需要额外的逻辑才能在适当的行索引处重新显示 "hidden" 节点(已从网格中删除)(这是一个相当棘手的问题)。

注意:您可能会考虑使用 TableView 而不是 GridPane。通过操作支持 TableView 的项目列表,向 TableView 添加和删除节点非常简单。当然,我知道 TableView 并不是解决所有此类问题的合适方法(因为 TableView 带有许多其他功能,例如 headers 和排序,您可能不希望拥有这些功能)。