gpt4 book ai didi

JavaFX: 'disabling' TableView 行和列

转载 作者:行者123 更新时间:2023-12-01 09:56:03 31 4
gpt4 key购买 nike

我有一个 TableView,希望允许用户禁用单独的行和列。

表数据由 API 提供,因此行数和列数的确切数量要到运行时才能知道,但通常为 4-30 行和 15-25 列。理想情况下,第一列/行是标题,最后一行是页脚(即:上面/侧面的数据摘要)。一旦用户执行了一些其他操作,他们应该能够禁用行或列 - 最好通过单击标题 - 从而从摘要中删除这些数据。

行/列应该仍然可见。不需要排序。不需要编辑。

我知道 JavaFX 仅真正支持列标题,而不是行标题,当然也不支持页脚。这让我认为最好的选择是:

  • Remove the TableView headers完全。
  • 将第一列/最后一行设置为页眉/页脚。
  • 将CellSelectionEnabled设置为true
  • 如果所选单元格是标题单元格,则“禁用”该行或列;可能通过结合 CSS 样式和从摘要中删除单元格值来实现。
  • 如果所选单元格不是标题单元格,请执行不同的操作。
  • 如果再次点击标题单元格,则重新启用该行或列。

这是最好的方法吗?是否有任何第三方库可以使工作变得更轻松?是否值得完全放弃 TableView 并使用 GridPane?

谢谢。

最佳答案

正如@Jacks 所指出的,这似乎没有捷径。这就是我解决问题的方法。

首先,我们hide the table header并允许单独选择单元格。 updateTable()n 秒调用一次方法;它模拟 ScheduledService API 调用。 MyRow对象只是 ObservableList<TableCell> 的包装器,我们使用它是因为在运行时之前我们不知道会有多少列。

COLUMN_HEADER, ROW_FOOTER等都是枚举。

private void updateTable() {
Pane header = (Pane) myTable.lookup("TableHeaderRow");
header.setVisible(false);
myTable.getSelectionModel().setCellSelectionEnabled(true);
myTable.setLayoutY(-header.getHeight());
myTable.autosize();

List<MyRow> list = new CopyOnWriteArrayList();
Integer maxRows = 5, maxColumns = 5; // For example
MyRow row;
for (int rowId = 0; rowId <= maxRows; rowId++) {
Boolean isEmpty = myTable.getColumns().isEmpty();
row = new MyRow();
Integer total = 0;
for (int colId = 0; colId <= maxColumns; colId++) {
if (isEmpty) {
myTable.getColumns().add(createReactiveColumn());
}
TableCell cell = new MyTableCell();
if (rowId == 0 && colId == 0) {
// Top-left cell
} else if (rowId == 0) {
// Column title
cell.setUserData(COLUMN_HEADER);
cell.setText("CH" + Integer.toString(colId));
} else if (colId == 0) {
// Row title
cell.setUserData(ROW_HEADER);
cell.setText("RH" + Integer.toString(rowId));
} else if (colId == maxColumns) {
// Row 'footer'
cell.setUserData(ROW_FOOTER);
cell.setText(Integer.toString(total));
} else if (rowId == maxRows) {
// Column 'footer'
cell.setUserData(COLUMN_FOOTER);
cell.setText("CF" + Integer.toString(rowId));
} else {
// Data
Integer r = new Random().nextInt(9); // Simulate API data
if (!this.disabledColumns.contains(myTable.getColumns().get(colId))) {
total += r; // Sum of each enabled cell
}
cell.setUserData(DATA);
cell.setText(Integer.toString(r));
}
row.add(cell);
}
list.add(row);
}
myTable.getItems().setAll(list);
}

TableColumn只是使用 setCellFactory()方法:

private TableColumn<MyRow, String> createReactiveColumn() {

TableColumn<MyRow, String> column = new TableColumn<MyRow, String>();
column.setCellFactory(new Callback<TableColumn<MyRow, String>, TableCell<MyRow, String>>() {
@Override
public TableCell<MyRow, String> call(TableColumn<MyRow, String> param) {
return new MyTableCell();
}
});
column.setSortable(FALSE);
column.setMinWidth(40d);

return column;
}

MyTableCell添加 MOUSE_CLICKED事件处理程序,以及从更新的 TableCell 复制文本.

private class MyTableCell extends TableCell<MyRow, String> {

Boolean hasEventHandler = FALSE;

@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty && getTableRow() != null && getTableRow().getItem() != null) {
MyRow er = (MyRow) getTableRow().getItem();
TableCell cell = er.get(getTableView().getColumns().indexOf(getTableColumn()));
this.setText(cell.getText());
if (cell.getUserData() instanceof MyTableCellEnum) {
MyTableCellEnumcellType = (MyTableCellEnum) cell.getUserData();
if (null != cellType && !hasEventHandler) {
switch (cellType) {
case COLUMN_HEADER:
addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
toggleColumn(getTableColumn());
}
});
hasEventHandler = TRUE;
break;
case ROW_HEADER:
addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
toggleRow(getTableRow());
}
});
hasEventHandler = TRUE;
break;
case DATA:
addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// Do other action on selection
}
});
break;
default:
break;
}
}
}
}
}
}

最后,切换方法只是在一组禁用 TableRow 之间交换行/列。/TableColumn对象并更新 CSS:

private void toggleRow(TableRow tableRow) {
if (this.disabledRows.contains(tableRow)) {
this.disabledRows.remove(tableRow);
tableRow.getStyleClass().remove("cell-disabled");
} else {
this.disabledRows.add(tableRow);
tableRow.getStyleClass().add("cell-disabled");
}
}

private void toggleColumn(TableColumn tableColumn) {
System.out.println(tableColumn);
if (this.disabledColumns.contains(tableColumn)) {
this.disabledColumns.remove(tableColumn);
tableColumn.getStyleClass().remove("cell-disabled");
} else {
this.disabledColumns.add(tableColumn);
tableColumn.getStyleClass().add("cell-disabled");
}
}

它有效,我对此非常满意。包含hasEventHandler boolean 值并不理想:它看起来有点老套,但我找不到任何其他方法只注册一次事件处理程序,同时确保它确实有效。

欢迎提出改进意见和建议。如果有更好的想法,我会在接受我自己的答案之前几天将其保留。

关于JavaFX: 'disabling' TableView 行和列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37206084/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com