我想在网格窗格中添加一条不可见的行。然后我想根据用户选择显示和隐藏它。我设法使一般功能正常工作,但问题是当行内容被隐藏时,有一个额外的空间。我不确定这是实际的行还是vgap?无论如何,我想摆脱这个额外的空间。 这是我的网格窗格:
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 :(得分:2)
如评论(link to comment)中所述:
隐藏时将高度更改为0。
答案 1 :(得分:1)
我认为处理此问题的最佳方法是实际从网格窗格中删除该行,而不是尝试使该行“不可见”。在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();
}
}
}
上面的程序只是一个大纲,需要额外的逻辑来在适当的行索引上重新显示“隐藏”节点(已从网格中删除)(这是一个相当棘手的问题)。
注意:您可以考虑使用TableView而不是GridPane。通过操作支持TableView的项目列表,向TableView添加和删除节点是非常简单的。当然,我理解TableView不适合所有这类问题(因为TableView带有一些其他功能,比如标题和排序,你可能不希望这样)。