Skip to content

Instantly share code, notes, and snippets.

@james-d
Last active October 2, 2020 07:15
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save james-d/8187590 to your computer and use it in GitHub Desktop.
Save james-d/8187590 to your computer and use it in GitHub Desktop.
Example of attaching context-specific context menus to a TableView. Menus are attached for the TableView context, TableRow context, and TableCell context.
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
private final StringProperty firstName ;
private final StringProperty lastName ;
private final StringProperty email ;
public Person(String firstName, String lastName, String email) {
this.firstName = new SimpleStringProperty(this, "firstName", firstName);
this.lastName = new SimpleStringProperty(this, "lastName", lastName);
this.email = new SimpleStringProperty(this, "email", email);
}
public Person() {
this("","","");
}
public final String getFirstName() {
return firstName.get();
}
public final void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public final StringProperty firstNameProperty() {
return firstName ;
}
public final String getLastName() {
return lastName.get();
}
public final void setLastName(String lastName) {
this.lastName.set(lastName);
}
public final StringProperty lastNameProperty() {
return lastName ;
}
public final String getEmail() {
return email.get();
}
public final void setEmail(String email) {
this.email.set(email);
}
public final StringProperty emailProperty() {
return email ;
}
@Override
public String toString() {
return getFirstName() + " " + getLastName() ;
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableViewSample extends Application {
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final TableView<Person> table = new TableView<>();
table.getItems().addAll(
new Person("Jacob", "Smith", "jacob.smith@example.com"),
new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
new Person("Ethan", "Williams", "ethan.williams@example.com"),
new Person("Emma", "Jones", "emma.jones@example.com"),
new Person("Michael", "Brown", "michael.brown@example.com"));
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
firstNameCol.setMinWidth(150);
lastNameCol.setMinWidth(150);
emailCol.setMinWidth(150);
table.getColumns().addAll(Arrays.asList(firstNameCol, lastNameCol, emailCol));
final ContextMenu tableContextMenu = new ContextMenu();
final MenuItem addMenuItem = new MenuItem("Add...");
final MenuItem deleteSelectedMenuItem = new MenuItem("Delete selected");
deleteSelectedMenuItem.disableProperty().bind(Bindings.isEmpty(table.getSelectionModel().getSelectedItems()));
deleteSelectedMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
final List<Person> selectedPeople = new ArrayList<>(table.getSelectionModel().getSelectedItems());
table.getItems().removeAll(selectedPeople);
}
});
tableContextMenu.getItems().addAll(addMenuItem, deleteSelectedMenuItem);
table.setContextMenu(tableContextMenu);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
@Override
public TableRow<Person> call(TableView<Person> tableView) {
final TableRow<Person> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu();
ContextMenu tableMenu = tableView.getContextMenu();
if (tableMenu != null) {
rowMenu.getItems().addAll(tableMenu.getItems());
rowMenu.getItems().add(new SeparatorMenuItem());
}
MenuItem editItem = new MenuItem("Edit");
MenuItem removeItem = new MenuItem("Delete");
rowMenu.getItems().addAll(editItem, removeItem);
row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu) null));
return row;
}
});
emailCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
@Override
public TableCell<Person, String> call(TableColumn<Person, String> col) {
final TableCell<Person, String> cell = new TableCell<>();
cell.itemProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
if (newValue != null) {
final ContextMenu cellMenu = new ContextMenu();
final TableRow<?> row = cell.getTableRow();
final ContextMenu rowMenu;
if (row != null) {
rowMenu = cell.getTableRow().getContextMenu();
if (rowMenu != null) {
cellMenu.getItems().addAll(rowMenu.getItems());
cellMenu.getItems().add(new SeparatorMenuItem());
} else {
final ContextMenu tableMenu = cell.getTableView().getContextMenu();
if (tableMenu != null) {
cellMenu.getItems().addAll(tableMenu.getItems());
cellMenu.getItems().add(new SeparatorMenuItem());
}
}
}
final MenuItem emailMenuItem = new MenuItem("Email");
emailMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Email " + cell.getTableRow().getItem() + " at " + cell.getItem());
}
});
cellMenu.getItems().add(emailMenuItem);
cell.setContextMenu(cellMenu);
} else {
cell.setContextMenu(null);
}
}
});
cell.textProperty().bind(cell.itemProperty());
return cell;
}
});
root.setCenter(table);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
@cyberterror
Copy link

nice thank you!

@daveream
Copy link

clear and concise and just what I needed - all three contexts - thanks!

@Kwonkyu
Copy link

Kwonkyu commented Sep 10, 2020

table.getSelectionModel().getSelectedItems()
it helps me a lot! thanks

@UralovAbdulhay
Copy link

table.setRowFactory(new Callback<TableView, TableRow>() {...}
good job, it was useful for me, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment