Reputation: 327
Is there a way to get an mouse-click on an Header of a Table?
Why i need this?
I have a Table with many Columns. But only a specific witdth for the whole Table. To avoid scrolling, i want to give each Column an specific width (50 or so), and just if you click on an header, this column will expand so you can read the content. If you click on another header, the previous one collapse.
Hopefully someone can help me:)
Upvotes: 3
Views: 5399
Reputation: 825
// Step 0: call setOnShown(...).
stage.setOnShown(event -> {
setHeaderClickListeners(); // Call this method when the stage is shown.
});
And then you create a method setHeaderClickListeners()
, as follows:
private void setHeaderClickListeners() {
// Step 1: Get the table header row.
TableHeaderRow headerRow = null;
for (Node n : ((TableViewSkin<?>) tableView.getSkin()).getChildren()) {
if (n instanceof TableHeaderRow) {
headerRow = (TableHeaderRow) n;
}
}
if (headerRow == null) {
return;
}
// Step 2: Get the list of the header columns.
NestedTableColumnHeader ntch = (NestedTableColumnHeader) headerRow.getChildren().get(1);
ObservableList<TableColumnHeader> headers = ntch.getColumnHeaders();
// Step 3: Add click listener to the header columns.
for (int i = 0; i < headers.size(); i++) {
TableColumnHeader header = headers.get(i);
final int index = i;
header.setOnMouseClicked(mouseEvent -> {
// Optional:
// Get the TableColumnBase (which is the object responsible
// for displaying the content of the column.)
TableColumnBase column = header.getTableColumn();
// Step 4: Handle double mouse click event.
if (mouseEvent.getButton() == MouseButton.PRIMARY && mouseEvent.getClickCount() == 2) {
P.x("Header cell " + index + " clicked! " + column.getText());
}
});
}
}
Upvotes: 0
Reputation: 36743
Unfortunately there isn't a nice way to do this. The only public API option is to replace the "graphic" of the column with your own label, and then add a mouse listener to that. For this to work you also need to clear any existing column text.
Note that columns by default have click listeners to implement sorting, it seems you don't want this behaviour, so you'll also need to call column.setSortable(false)
@Override
public void start(Stage primaryStage) throws Exception {
TableView<String> tableView = new TableView<>();
TableColumn<String, Object> x = new TableColumn<>("x");
tableView.getColumns().add(x);
TableColumn<String, Object> y = new TableColumn<>("");
tableView.getColumns().add(y);
x.setSortable(false);
y.setSortable(false);
makeHeader(x, "X", 0);
makeHeader(y, "Y", 1);
EventHandler<? super MouseEvent> handler = event -> {
System.out.println("Column clicked " + ((Node)event.getTarget()).getProperties().get("index"));
};
x.getGraphic().addEventFilter(MouseEvent.MOUSE_CLICKED, handler);
y.getGraphic().addEventFilter(MouseEvent.MOUSE_CLICKED, handler);
primaryStage.setScene(new Scene(tableView));
primaryStage.show();
}
private void makeHeader(TableColumn<?, ?> target, String name, int index) {
VBox vBox = new VBox(new Label(name));
vBox.setAlignment(Pos.CENTER);
vBox.getProperties().put("index", index);
target.setGraphic(vBox);
target.setText("");
}
Upvotes: 4