在 TableView JavaFX 中更改值列 header
Change value column header in TableView JavaFX
我正在尝试在 JavaFX 中创建一个 TableView,用户可以在其中通过双击 table header 来更改列 header 的值。
应出现一个文本框,在填写新值后,应将该值分配给列 header.
Example of output below
与 James 评论中概述的方法略有不同:
- 使用 table
注册鼠标处理程序
- 双击(这会干扰排序...但这是一个不同的问题),找到代表 table列的 TableColumnHeader,如果有的话
- 创建并连接一个 TextField 并将其设置为列的图形(如 James 所建议的)
请注意,TableColumnHeader 的包是依赖于版本的,对于 fx8,它被认为是内部 api 驻留在 com.xx.skin,对于 fx9,它是 public 在 javafx.xx.skin。
例子:
public class TableHeaderWithInput extends Application {
TableView<Locale> table;
protected void installHeaderHandler(Observable s) {
table.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
if (e.isPrimaryButtonDown() && e.getClickCount() > 1) {
EventTarget target = e.getTarget();
TableColumnBase<?, ?> column = null;
while (target instanceof Node) {
target = ((Node) target).getParent();
// beware: package of TableColumnHeader is version specific
if (target instanceof TableColumnHeader) {
column = ((TableColumnHeader) target).getTableColumn();
if (column != null) break;
}
}
if (column != null) {
TableColumnBase<?,?> tableColumn = column;
TextField textField = new TextField(column.getText());
textField.setMaxWidth(column.getWidth());
textField.setOnAction(a -> {
tableColumn.setText(textField.getText());
tableColumn.setGraphic(null);
});
textField.focusedProperty().addListener((src, ov, nv) -> {
if (!nv) tableColumn.setGraphic(null);
});
column.setGraphic(textField);
textField.requestFocus();
}
e.consume();
}
});
}
private Parent getContent() {
table = new TableView<>(FXCollections.observableArrayList(
Locale.getAvailableLocales()));
table.setTableMenuButtonVisible(true);
// quick hack: don't let sorting interfere ...
table.setSortPolicy(e -> {return false;});
TableColumn<Locale, String> countryCode = new TableColumn<>("CountryCode");
countryCode.setCellValueFactory(new PropertyValueFactory<>("country"));
TableColumn<Locale, String> language = new TableColumn<>("Language");
language.setCellValueFactory(new PropertyValueFactory<>("language"));
table.getColumns().addAll(countryCode, language);
table.skinProperty().addListener(this::installHeaderHandler);
BorderPane pane = new BorderPane(table);
return pane;
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent(), 800, 400));
primaryStage.setTitle(FXUtils.version());
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TableHeaderWithInput.class.getName());
}
我正在尝试在 JavaFX 中创建一个 TableView,用户可以在其中通过双击 table header 来更改列 header 的值。 应出现一个文本框,在填写新值后,应将该值分配给列 header.
Example of output below
与 James 评论中概述的方法略有不同:
- 使用 table 注册鼠标处理程序
- 双击(这会干扰排序...但这是一个不同的问题),找到代表 table列的 TableColumnHeader,如果有的话
- 创建并连接一个 TextField 并将其设置为列的图形(如 James 所建议的)
请注意,TableColumnHeader 的包是依赖于版本的,对于 fx8,它被认为是内部 api 驻留在 com.xx.skin,对于 fx9,它是 public 在 javafx.xx.skin。
例子:
public class TableHeaderWithInput extends Application {
TableView<Locale> table;
protected void installHeaderHandler(Observable s) {
table.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
if (e.isPrimaryButtonDown() && e.getClickCount() > 1) {
EventTarget target = e.getTarget();
TableColumnBase<?, ?> column = null;
while (target instanceof Node) {
target = ((Node) target).getParent();
// beware: package of TableColumnHeader is version specific
if (target instanceof TableColumnHeader) {
column = ((TableColumnHeader) target).getTableColumn();
if (column != null) break;
}
}
if (column != null) {
TableColumnBase<?,?> tableColumn = column;
TextField textField = new TextField(column.getText());
textField.setMaxWidth(column.getWidth());
textField.setOnAction(a -> {
tableColumn.setText(textField.getText());
tableColumn.setGraphic(null);
});
textField.focusedProperty().addListener((src, ov, nv) -> {
if (!nv) tableColumn.setGraphic(null);
});
column.setGraphic(textField);
textField.requestFocus();
}
e.consume();
}
});
}
private Parent getContent() {
table = new TableView<>(FXCollections.observableArrayList(
Locale.getAvailableLocales()));
table.setTableMenuButtonVisible(true);
// quick hack: don't let sorting interfere ...
table.setSortPolicy(e -> {return false;});
TableColumn<Locale, String> countryCode = new TableColumn<>("CountryCode");
countryCode.setCellValueFactory(new PropertyValueFactory<>("country"));
TableColumn<Locale, String> language = new TableColumn<>("Language");
language.setCellValueFactory(new PropertyValueFactory<>("language"));
table.getColumns().addAll(countryCode, language);
table.skinProperty().addListener(this::installHeaderHandler);
BorderPane pane = new BorderPane(table);
return pane;
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent(), 800, 400));
primaryStage.setTitle(FXUtils.version());
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TableHeaderWithInput.class.getName());
}