JavaFX Set table rowfactory of table view on Button click - java

i am writing a table drag and drop rearrage form application in javafx. In this application i intend to edit the table order by drag and drop, i have formally written the drag and drop for my Table from my previous searching but what is bugging me is, i would only want to set the drag and drop tablerowfactory only when a button is clicked
Here is my Code:
'''
import java.util.function.Function;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TableViewDragRows extends Application {
private static final DataFormat SERIALIZED_MIME_TYPE = new DataFormat("application/x-java-serialized-object");
public TableView<Person> tableView;
#Override
public void start(Stage primaryStage) {
tableView = new TableView<>();
tableView.getColumns().add(createCol("First Name", Person::firstNameProperty, 150));
tableView.getColumns().add(createCol("Last Name", Person::lastNameProperty, 150));
tableView.getColumns().add(createCol("Email", Person::emailProperty, 200));
tableView.getItems().addAll(
new Person("Jacob", "Smith", "jacob.smith#example.com","1"),
new Person("Isabella", "Johnson", "isabella.johnson#example.com","2"),
new Person("Ethan", "Williams", "ethan.williams#example.com","3"),
new Person("Emma", "Jones", "emma.jones#example.com","4"),
new Person("Michael", "Brown", "michael.brown#example.com","5")
);
Button order = new Button("Set Order");
order.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
tableView.setRowFactory(tv -> {
TableRow<Person> row = new TableRow<>();
row.setOnDragDetected(event -> {
if (! row.isEmpty()) {
Integer index = row.getIndex();
Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
db.setDragView(row.snapshot(null, null));
ClipboardContent cc = new ClipboardContent();
cc.put(SERIALIZED_MIME_TYPE, index);
db.setContent(cc);
event.consume();
}
});
row.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(SERIALIZED_MIME_TYPE)) {
if (row.getIndex() != ((Integer)db.getContent(SERIALIZED_MIME_TYPE)).intValue()) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
}
});
row.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(SERIALIZED_MIME_TYPE)) {
int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE);
Person draggedPerson = tableView.getItems().remove(draggedIndex);
int dropIndex ;
if (row.isEmpty()) {
dropIndex = tableView.getItems().size() ;
} else {
dropIndex = row.getIndex();
}
tableView.getItems().add(dropIndex, draggedPerson);
event.setDropCompleted(true);
tableView.getSelectionModel().select(dropIndex);
event.consume();
}
});
return row ;
});
}
});
order.pressedProperty().addListener((obs, wasFocused, isNowPressed) -> {
if (isNowPressed) {
Platform.runLater(() -> tableView.setRowFactory(tv -> {
TableRow<Person> row = new TableRow<>();
row.setOnDragDetected(event -> {
if (! row.isEmpty()) {
Integer index = row.getIndex();
Dragboard db = row.startDragAndDrop(TransferMode.MOVE);
db.setDragView(row.snapshot(null, null));
ClipboardContent cc = new ClipboardContent();
cc.put(SERIALIZED_MIME_TYPE, index);
db.setContent(cc);
event.consume();
}
});
row.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(SERIALIZED_MIME_TYPE)) {
if (row.getIndex() != ((Integer)db.getContent(SERIALIZED_MIME_TYPE)).intValue()) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
}
});
row.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
if (db.hasContent(SERIALIZED_MIME_TYPE)) {
int draggedIndex = (Integer) db.getContent(SERIALIZED_MIME_TYPE);
Person draggedPerson = tableView.getItems().remove(draggedIndex);
int dropIndex ;
if (row.isEmpty()) {
dropIndex = tableView.getItems().size() ;
} else {
dropIndex = row.getIndex();
}
tableView.getItems().add(dropIndex, draggedPerson);
event.setDropCompleted(true);
tableView.getSelectionModel().select(dropIndex);
event.consume();
}
});
return row ;
}));
}
});
Button button = new Button("Get Order");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
for(Person p: tableView.getItems()){
System.out.println(p.getid());
} }
});
VBox vbox = new VBox();
vbox.getChildren().addAll(tableView, button, order);
Scene scene = new Scene(new BorderPane(vbox), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private TableColumn<Person, String> createCol(String title,
Function<Person, ObservableValue<String>> mapper, double size) {
TableColumn<Person, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> mapper.apply(cellData.getValue()));
col.setPrefWidth(size);
return col ;
}
public class Person {
private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
private final StringProperty email = new SimpleStringProperty(this, "email");
private final StringProperty id = new SimpleStringProperty(this, "id");
public Person(String firstName, String lastName, String email, String id) {
this.firstName.set(firstName);
this.lastName.set(lastName);
this.email.set(email);
this.id.set(id);
}
public final StringProperty idProperty() {
return this.id;
}
public final String getid() {
return this.idProperty().get();
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
public final StringProperty emailProperty() {
return this.email;
}
public final String getEmail() {
return this.emailProperty().get();
}
public final void setEmail(final String email) {
this.emailProperty().set(email);
}
}
public static void main(String[] args) {
launch(args);
}
}
'''
The problem is the button order doesn't invoke the rowfactory

Related

JavaFX TableView Undo functionality

I have a table, and I create the columns in the following way:
#FXML
TableView<Row> tableView = new TableView<>();
private void createColumns(int numberOfColumns, Row firstRow, boolean errorsDisplayed) {
for (int i = 0; i < numberOfColumns; i++) {
int colNum = i;
TableColumn<Row, String> column = new TableColumn<>(firstRow.getCell(i).toString());
column.setCellValueFactory(param -> {
int index = param.getTableView().getColumns().indexOf(param.getTableColumn());
return new SimpleStringProperty(param.getValue().getLastCellNum() > index
? param.getValue().getCell(index).toString() : null);
});
if (!errorsDisplayed || (colNum != numberOfColumns - 1 && colNum != numberOfColumns - 2)) {
column.setCellFactory(TextFieldTableCell.forTableColumn());
column.setOnEditCommit(param -> param.getTableView().getItems().get(param.getTablePosition()
.getRow()).getCell(colNum).setCellValue(param.getNewValue()));
}
tableView.getColumns().add(column);
}
}
Is there a way I could store different states of the table in order to restore them when the undo button being pressed?
I create an app that can hopefully help. It is probably full of traps and pitfalls so don't attempt to use the code as it. I got the Undo/Redo ideas from here. Two Stack are used to implement the ideas. I got the code for the TableView from here. Changes are committed on focus lost.
Main
/*
Altered code from the following!
1. https://docs.oracle.com/javafx/2/ui_controls/table-view.htm
2. https://www.geeksforgeeks.org/implement-undo-and-redo-features-of-a-text-editor/
*/
import com.mycompany.javafxsimpletest.MyAction.MyActionType;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
public class App extends Application {
final private UndoRedo undoRedo = new UndoRedo();
final private TableView<Person> table = new TableView();
final private HBox hb = new HBox();
private ObservableList<Person> data;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
data = FXCollections.observableArrayList(
new Person(GenerateUniqueId.getUniqueId(), "Jacob", "Smith", "jacob.smith#example.com"),
new Person(GenerateUniqueId.getUniqueId(), "Isabella", "Johnson", "isabella.johnson#example.com"),
new Person(GenerateUniqueId.getUniqueId(), "Ethan", "Williams", "ethan.williams#example.com"),
new Person(GenerateUniqueId.getUniqueId(), "Emma", "Jones", "emma.jones#example.com"),
new Person(GenerateUniqueId.getUniqueId(), "Michael", "Brown", "michael.brown#example.com"));
//Since I added these Persons via code and not manually, I added that action here!
data.forEach((newPerson) -> {
undoRedo.addAction(new MyAction(MyActionType.ADD, null, newPerson.copy()));
System.out.println("Add Undo Action - \n\tActionType: " + MyActionType.ADD + "\n\tOld Person: " + null + "\n\tnew Person: " + newPerson);
});
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(450);
stage.setHeight(550);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(true);
Callback<TableColumn, TableCell> cellFactory = (TableColumn p) -> new EditingCell();
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
firstNameCol.setCellFactory(cellFactory);
firstNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
Person oldPerson = t.getTableView().getItems().get(t.getTablePosition().getRow());
Person newPerson = oldPerson.copy();
newPerson.setFirstName(t.getNewValue());
undoRedo.addAction(new MyAction(MyActionType.EDIT, oldPerson, newPerson));
System.out.println("Add Undo Action - \n\tActionType: " + MyActionType.EDIT + "\n\tOld Person: " + oldPerson + "\n\tnew Person: " + newPerson);
}
}
);
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("lastName"));
lastNameCol.setCellFactory(cellFactory);
lastNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
Person oldPerson = t.getTableView().getItems().get(t.getTablePosition().getRow());
Person newPerson = oldPerson.copy();
newPerson.setLastName(t.getNewValue());
undoRedo.addAction(new MyAction(MyActionType.EDIT, oldPerson, newPerson));
System.out.println("Add Undo Action - \n\tActionType: " + MyActionType.EDIT + "\n\tOld Person: " + oldPerson + "\n\tnew Person: " + newPerson);
}
}
);
TableColumn emailCol = new TableColumn("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("email"));
emailCol.setCellFactory(cellFactory);
emailCol.setOnEditCommit(
new EventHandler<CellEditEvent<Person, String>>() {
#Override
public void handle(CellEditEvent<Person, String> t) {
Person oldPerson = t.getTableView().getItems().get(t.getTablePosition().getRow());
Person newPerson = oldPerson.copy();
newPerson.setEmail(t.getNewValue());
undoRedo.addAction(new MyAction(MyActionType.EDIT, oldPerson, newPerson));
System.out.println("Add Undo Action - \n\tActionType: " + MyActionType.EDIT + "\n\tOld Person: " + oldPerson + "\n\tnew Person: " + newPerson);
}
}
);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final TextField addFirstName = new TextField();
addFirstName.setPromptText("First Name");
addFirstName.setMaxWidth(firstNameCol.getPrefWidth());
final TextField addLastName = new TextField();
addLastName.setMaxWidth(lastNameCol.getPrefWidth());
addLastName.setPromptText("Last Name");
final TextField addEmail = new TextField();
addEmail.setMaxWidth(emailCol.getPrefWidth());
addEmail.setPromptText("Email");
final Button addButton = new Button("Add");
addButton.setOnAction((ActionEvent e) -> {
Person newPerson = new Person(GenerateUniqueId.getUniqueId(),addFirstName.getText(), addLastName.getText(), addEmail.getText());
data.add(newPerson);
addFirstName.clear();
addLastName.clear();
addEmail.clear();
undoRedo.addAction(new MyAction(MyActionType.ADD, null, newPerson.copy()));
System.out.println("Add Undo Action - ActionType: " + MyActionType.ADD + "\tPerson: " + newPerson);
});
Button btnUndo = new Button("<");
btnUndo.setOnAction((t) -> {
if(!undoRedo.isUndoEmpty())
{
MyAction myUndoAction = undoRedo.getUndo();
Person oldPerson = (Person)myUndoAction.getOldAction();
Person newPerson = (Person)myUndoAction.getNewAction();
System.out.println("Add Undo Action - \n\tActionType: " + myUndoAction.getActionType() + "\n\tOld Person: " + oldPerson + "\n\tnew Person: " + newPerson);
if(myUndoAction.getActionType() == MyActionType.ADD)
{
data.remove(data.indexOf(data.stream().filter((z) -> z.getId() == newPerson.getId()).findFirst().get()));
}
else if(myUndoAction.getActionType() == MyActionType.EDIT)
{
data.set(data.indexOf(data.stream().filter((z) -> z.getId() == oldPerson.getId()).findFirst().get()), oldPerson);
}
}
});
Button btnRedo = new Button(">");
btnRedo.setOnAction((t) -> {
if(!undoRedo.isRedoEmpty())
{
MyAction myRedoAction = undoRedo.getRedo();
Person oldPerson = (Person)myRedoAction.getOldAction();
Person newPerson = (Person)myRedoAction.getNewAction();
System.out.println("Add Undo Action - \n\tActionType: " + myRedoAction.getActionType() + "\n\tOld Person: " + oldPerson + "\n\tnew Person: " + newPerson);
if(myRedoAction.getActionType() == MyActionType.ADD)
{
data.add(newPerson.getId(), newPerson);
}
else if(myRedoAction.getActionType() == MyActionType.EDIT)
{
data.set(data.indexOf(data.stream().filter((z) -> z.getId() == newPerson.getId()).findFirst().get()), newPerson);
}
}
});
hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton, btnUndo, btnRedo);
hb.setSpacing(3);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, hb);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
#Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) {
if (!arg2) {
commitEdit(textField.getText());
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
}
Person
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
private final IntegerProperty id;
private final StringProperty firstName;
private final StringProperty lastName;
private final StringProperty email;
public Person(int id, String fName, String lName, String email) {
this.id = new SimpleIntegerProperty(id);
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
public int getId()
{
return id.get();
}
#Override public String toString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("id: ").append(this.id.get())
.append("\tName:").append(this.firstName.get()).append(" ").append(this.lastName.get())
.append("\temail: ").append(this.email.get());
return stringBuilder.toString();
}
public Person copy()
{
Person copyPerson = new Person(this.id.get(), this.firstName.get(), this.lastName.get(), this.email.get());
return copyPerson;
}
}
MyAction
/**
*
* #author blj0011(sedj601)
* #param <T>
*/
public class MyAction<T>
{
public enum MyActionType {
ADD,
DELETE,
EDIT
}
private final T oldAction;
private final T newAction;
private final MyActionType myActionType;
public MyAction(MyActionType actionType, T oldAction, T newAction) {
this.oldAction = oldAction;
this.newAction = newAction;
this.myActionType = actionType;
}
public T getOldAction()
{
return this.oldAction;
}
public T getNewAction()
{
return this.newAction;
}
public MyActionType getActionType()
{
return this.myActionType;
}
}
UndoRedo
import java.util.Stack;
/**
*
* author 2. https://www.geeksforgeeks.org/implement-undo-and-redo-features-of-a-text-editor/
*
*/
public class UndoRedo {
private final Stack<MyAction> undo = new Stack();
private final Stack<MyAction> redo = new Stack();
public void addAction(MyAction myAction)
{
undo.push(myAction);
}
// Function to perform
// "UNDO" operation
public MyAction getUndo()
{
MyAction myAction = undo.peek();
undo.pop();
redo .push(myAction);
return myAction;
}
// Function to perform
// "REDO" operation
public MyAction getRedo()
{
MyAction myAction = redo.peek();
redo.pop();
undo.push(myAction);
return myAction;
}
//Check if stack is empty before attempting to do use getUndo()!
public boolean isUndoEmpty()
{
return undo.empty();
}
//Check if stack is empty before attempting to do use getRedo()!
public boolean isRedoEmpty()
{
return redo.empty();
}
}
**GenerateUniqueId
/**
*
* #author blj0011(sedj601)
*/
public class GenerateUniqueId {
static AtomicInteger uniqueIdGenerator = new AtomicInteger();
public static int getUniqueId()
{
return uniqueIdGenerator.getAndIncrement();
}
}

How to center the text in TreeTableView Column?

I've a JFXTreeTableView and i want to center the text of the data for each column.
there is one of my creating columns code :
JFXTreeTableColumn<TableData, String> DrinkColumn = new JFXTreeTableColumn<>("Drink");
DrinkColumn.setPrefWidth(100);
DrinkColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<TableData, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<TableData, String> param) {
return param.getValue().getValue().Drink;
}
}
);
I don't use JFoenix, but using a standard TreeTableView, the following external CSS will center the text in tree table cells:
.tree-table-cell {
-fx-alignment: center ;
}
Here's a SSCCE (the code above goes in style.css):
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class TreeTableViewTest extends Application {
#Override
public void start(Stage primaryStage) {
TreeTableView<Item> table = new TreeTableView<>();
TreeTableColumn<Item, String> col = new TreeTableColumn<>("Item");
col.setCellValueFactory(cellData -> cellData.getValue().getValue().nameProperty());
col.setPrefWidth(250);
table.getColumns().add(col);
TreeTableColumn<Item, Number> valueCol = new TreeTableColumn<>("Value");
valueCol.setCellValueFactory(cellData -> cellData.getValue().getValue().valueProperty());
valueCol.setPrefWidth(150);
table.getColumns().add(valueCol);
table.setRoot(createRandomTree(50));
Scene scene = new Scene(table);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
private TreeItem<Item> createRandomTree(int nItems) {
Random rng = new Random();
TreeItem<Item> root = new TreeItem<>(new Item("Item 1", rng.nextInt(1000)));
root.setExpanded(true);
List<TreeItem<Item>> items = new ArrayList<>();
items.add(root);
for (int i = 2 ; i <= nItems ; i++) {
TreeItem<Item> item = new TreeItem<>(new Item("Item "+i, rng.nextInt(1000)));
item.setExpanded(true);
items.get(rng.nextInt(items.size())).getChildren().add(item);
items.add(item);
}
return root ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
If you want to center only specific columns, then use a cell factory on the column and set a CSS class or PseudoClass on the cell:
valueCol.setCellFactory(column -> {
TreeTableCell<Item, Number> cell = new TreeTableCell<Item, Number>() {
#Override
protected void updateItem(Number value, boolean empty) {
super.updateItem(value, empty);
if (empty) {
setText(null);
} else {
setText(value.toString());
}
}
};
cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("centered"), true);
return cell ;
});
and modify the CSS accordingly:
.tree-table-cell:centered {
-fx-alignment: center ;
}
The latter version gives

right click event and double click event on tableview javafx

I am rewriting an application from swing to javafx.
I do not understand how to implement a double click event and a right click event on the same row of a tableview.
Separately they work ok.
Thi is my code for right click behaviour.
words_table.setRowFactory(
new Callback<TableView<WordsToFind>, TableRow<WordsToFind>>() {
#Override
public TableRow<WordsToFind> call(TableView<WordsToFind> tableView) {
final TableRow<WordsToFind> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu();
MenuItem removeItem = new MenuItem("Delete");
removeItem.setOnAction(e -> {
int wordid = words_table.getSelectionModel().getSelectedItem().getWordToFindId();
deleteWord(wordid);
words_table.getItems().remove(row.getItem());
});
rowMenu.getItems().addAll(removeItem);
row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu)null));
return row;
}
});
This is my code for double click behaviour
words_table.setRowFactory(
new Callback<TableView<WordsToFind>, TableRow<WordsToFind>>() {
#Override
public TableRow<WordsToFind> call(TableView<WordsToFind> tableView) {
final TableRow<WordsToFind> row = new TableRow<>();
row.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event){
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
some code here .....
}
}
});
return row;
}
});
Thanks Alb
Just put the row.setOnMouseClicked call in the call() method of the first row factory.
words_table.setRowFactory(tableView -> {
final TableRow<WordsToFind> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu();
MenuItem removeItem = new MenuItem("Delete");
removeItem.setOnAction(e -> {
int wordid = words_table.getSelectionModel().getSelectedItem().getWordToFindId();
deleteWord(wordid);
words_table.getItems().remove(row.getItem());
});
rowMenu.getItems().addAll(removeItem);
row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu)null));
row.setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
// some code here .....
}
});
return row;
});
(I converted the anonymous inners classes to lambda expressions for readability.)
Here is a complete example that demonstrates this working:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class RowFactoryExample extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Value", Item::valueProperty));
table.getItems().setAll(createData());
table.setRowFactory(tableView -> {
final TableRow<Item> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu();
MenuItem removeItem = new MenuItem("Delete");
removeItem.setOnAction(e -> {
table.getItems().remove(row.getItem());
});
rowMenu.getItems().addAll(removeItem);
row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu)null));
row.setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
System.out.println("Double click on "+row.getItem().getName());
}
});
return row;
});
Scene scene = new Scene(table, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> TableColumn<S,T> column(String text, Function<S, ObservableValue<T>> prop) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
return col ;
}
private List<Item> createData() {
Random rng = new Random();
List<Item> data = new ArrayList<>();
for (int i = 1 ; i <= 100; i++) {
data.add(new Item("Item "+i, rng.nextInt(1000))) ;
}
return data ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
You can add both events to the row by doing row.setOnMouseClicked(..) itself as shown below
words_table.setRowFactory(
new Callback<TableView<WordsToFind>, TableRow<WordsToFind>>() {
#Override
public TableRow<WordsToFind> call(TableView<WordsToFind> tableView) {
final TableRow<WordsToFind> row = new TableRow<>();
row.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event){
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
//double click code here
}
else if(event.isSecondaryButtonDown()){
//right click code here
}
}
});
return row;
}
});

TableView - Attempting to make it behave like Excel

I'm attempting to make TableView behave like Excel. I am having trouble selected the correct cells.
In Excel, if you select a column(say 5 adjacent cells in the column) and then you click SHIFT + LEFT, excel will automatically select all corresponding left most cell.
e.g.
Say in Excel I have [A1][A2][A3] selects and then I click SHIFT + RIGHT, know the selected cells would be:
[A1][B1][A2][B2][A3][B3]
How can I achieve similar behavior with a TableView.
I've tried doing something like the following with no luck.
// Table view
TableView tv = new TableView();
// Some more code goes here
// Select right most element
tv.getSelectionModel().selectRightCell();
The problem with selectRightCell() or selectLeftCell() function is that it selects just a single cell (to the left or right of the selected cell) not the all left or right cell of the selected cells.
Here is sample code below, you can select by dragging by mouse or by pressing control+arrow keys.
import com.sun.javafx.scene.control.behavior.TableCellBehavior;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.Arrays;
public class DragSelectionTable extends Application {
private TableView<Person> table = new TableView<Person>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
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")
);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(450);
stage.setHeight(500);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
final Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory = new DragSelectionCellFactory();
firstNameCol.setCellFactory(cellFactory);
lastNameCol.setCellFactory(cellFactory);
emailCol.setCellFactory(cellFactory);
table.setEditable(true);
table.setItems(data);
table.getColumns().addAll(Arrays.asList(firstNameCol, lastNameCol, emailCol));
table.getSelectionModel().setCellSelectionEnabled(true);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.addEventHandler(KeyEvent.KEY_RELEASED, new ControlDownSelectionEventHandler());
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public class DragSelectionCellFactory implements Callback<TableColumn<Person, String>, TableCell<Person, String>> {
#Override
public TableCell<Person, String> call(final TableColumn<Person, String> col) {
return new DragSelectionCell();
}
}
public class DragSelectionCell extends TableCell<Person, String> {
public DragSelectionCell() {
setOnDragDetected(new DragDetectedEventHandler(this));
setOnMouseDragEntered(new DragEnteredEventHandler(this));
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
setText(item);
}
}
}
public class DragDetectedEventHandler implements EventHandler<MouseEvent> {
TableCell<Person, String> tableCell;
public DragDetectedEventHandler(TableCell<Person, String> tableCell) {
this.tableCell = tableCell;
}
#Override
public void handle(final MouseEvent event) {
tableCell.startFullDrag();
}
}
public class DragEnteredEventHandler implements EventHandler<MouseDragEvent> {
TableCell<Person, String> tableCell;
public DragEnteredEventHandler(TableCell<Person, String> tableCell) {
this.tableCell = tableCell;
}
#Override
public void handle(final MouseDragEvent event) {
performSelection(tableCell.getTableView(), tableCell.getTableColumn(), tableCell.getIndex());
}
}
public class ControlDownSelectionEventHandler implements EventHandler<KeyEvent> {
#Override
public void handle(final KeyEvent event) {
KeyCode code = event.getCode();
if (event.isShiftDown() && (KeyCode.UP.equals(code) || KeyCode.DOWN.equals(code) || KeyCode.LEFT.equals(code) || KeyCode.RIGHT.equals(code))) {
int index = table.getFocusModel().getFocusedCell().getRow();
TableColumn column = table.getFocusModel().getFocusedCell().getTableColumn();
performSelection(table, column, index);
}
}
}
protected void performSelection(TableView<Person> table, TableColumn<Person, String> column, int index) {
final TablePositionBase anchor = TableCellBehavior.getAnchor(table, table.getFocusModel().getFocusedCell());
int columnIndex = table.getVisibleLeafIndex(column);
int minRowIndex = Math.min(anchor.getRow(), index);
int maxRowIndex = Math.max(anchor.getRow(), index);
TableColumnBase minColumn = anchor.getColumn() < columnIndex ? anchor.getTableColumn() : column;
TableColumnBase maxColumn = anchor.getColumn() >= columnIndex ? anchor.getTableColumn() : column;
table.getSelectionModel().clearSelection();
final int minColumnIndex = table.getVisibleLeafIndex((TableColumn) minColumn);
final int maxColumnIndex = table.getVisibleLeafIndex((TableColumn) maxColumn);
for (int _row = minRowIndex; _row <= maxRowIndex; _row++) {
for (int _col = minColumnIndex; _col <= maxColumnIndex; _col++) {
table.getSelectionModel().select(_row, table.getVisibleLeafColumn(_col));
}
}
table.getFocusModel().focus(index, column);
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}
}

javafx tableview updates data only after sorting

I have two javafx tableviews. If I change a value in the first one, the second one shows the changes only after sorting (although the model is updated).
My entities
package Entity;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
public class Arbeitgeber {
private SimpleIntegerProperty id = new SimpleIntegerProperty();
private SimpleStringProperty name = new SimpleStringProperty();
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
...
package Entity;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private SimpleIntegerProperty id = new SimpleIntegerProperty();
private SimpleStringProperty name = new SimpleStringProperty();
private SimpleStringProperty gruppe = new SimpleStringProperty();
private ObjectProperty<Arbeitgeber> arbeitgeber = new SimpleObjectProperty<>();
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
...
My testcase :
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import Entity.Arbeitgeber;
import Entity.Person;
public class TableviewTest extends Application {
private TableView<Arbeitgeber> arbeitgeberTable;
private TableView<Person> personTable;
ObservableList<String> gruppeOptions =
FXCollections.observableArrayList(
"Arbeiter",
"Angestellter",
"Leiter"
);
private ObservableList<Arbeitgeber> arbeitgeberListe = FXCollections.observableArrayList(new Arbeitgeber(1, "Goldgräber Inc."), new Arbeitgeber(2, "Hamster GmbH"), new Arbeitgeber(3, "Wissen"));
private ObservableList<Person> personen = FXCollections.observableArrayList(
new Person(1, "Max Musterman", gruppeOptions.get(1), arbeitgeberListe.get(0)),
new Person(2, "Bernd Brot", gruppeOptions.get(0), arbeitgeberListe.get(0)),
new Person(3, "Fred Feuer", gruppeOptions.get(2), arbeitgeberListe.get(1)),
new Person(4, "Uli Stein", gruppeOptions.get(1), arbeitgeberListe.get(2)));
#Override
public void start(Stage primaryStage) throws Exception {
createArbeitgeberTableview();
createPersonTableview();
VBox vbox = new VBox(15);
Label aLabel = new Label("Arbeitgeber");
Label pLabel = new Label("Personen");
vbox.getChildren().addAll(aLabel, arbeitgeberTable, pLabel, personTable);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args
*/
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private TableView<Arbeitgeber> createArbeitgeberTableview() {
arbeitgeberTable = new TableView<>(arbeitgeberListe);
arbeitgeberTable.setEditable(true);
TableColumn<Arbeitgeber, Integer> idCol = new TableColumn<>("ID");
TableColumn nameCol = new TableColumn<>("Name");
idCol.setCellValueFactory(new PropertyValueFactory<Arbeitgeber, Integer>("id"));
nameCol.setCellValueFactory(new PropertyValueFactory<Arbeitgeber, String>("name"));
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
nameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Arbeitgeber,String>>() {
#Override
public void handle(CellEditEvent<Arbeitgeber, String> event) {
((Arbeitgeber) event.getTableView().getItems().get(event.getTablePosition().getRow())).setName(event.getNewValue());
for(Person p : personTable.getItems()) {
System.out.println(p.getArbeitgeber()); //shows the new value
}
}
});
arbeitgeberTable.getColumns().addAll(idCol, nameCol);
arbeitgeberTable.setTableMenuButtonVisible(true);
return arbeitgeberTable;
}
#SuppressWarnings("unchecked")
private TableView<Person> createPersonTableview(){
personTable = new TableView<>(personen);
TableColumn<Person, Integer> idCol = new TableColumn<>("ID");
TableColumn<Person, String> nameCol = new TableColumn<>("Name");
TableColumn<Person, String> gruppeCol = new TableColumn<>("Gruppe");
TableColumn<Person, Arbeitgeber> arbCol = new TableColumn<>("Arbeitgeber");
idCol.setCellValueFactory(new PropertyValueFactory<Person, Integer>("id"));
nameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
gruppeCol.setCellValueFactory(new PropertyValueFactory<Person, String>("gruppe"));
arbCol.setCellValueFactory(new PropertyValueFactory<Person, Arbeitgeber>("arbeitgeber"));
personTable.getColumns().addAll(idCol, nameCol, gruppeCol, arbCol);
personTable.setTableMenuButtonVisible(true);
return personTable;
}
}
I tried something like :
for(TableColumn t : personTable.getColumns()){
t.setVisible(false);
t.setVisible(true);
}
but it does not work. I would like to solve it without sorting. Does anyone have an idea?
Thanks.
Problem Restatement
As I understand it you have the following situation.
A person has a reference to an arbeitgeber
You display the arbeitgeber in one table and the person in another table.
The person table has an Arbeitgeber column which provides information on the related arbeitgeber.
In the arbeitgeber, the name of the arbeitgeber is editable.
When you edit arbeitgeber name, in the arbeitgeber table, you want the name update for the arbeitgeber to be automatically reflected in your person table.
Solution Approach
Ensure that entity objects have property access methods so that the values of the individual entity fields can be observed for changes and appropriate action taken.
public StringProperty nameProperty() {
return name;
}
Set up a binding between the cell values of the Arbeitgeber column in the person table and the arbeitgeber name.
In Java 7:
arbCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
return Bindings.selectString(
new ReadOnlyObjectWrapper<Object>(
p.getValue()
),
"arbeitgeber", "name"
);
}
});
In Java 8:
arbCol.setCellValueFactory(p ->
Bindings.selectString(p.getValue(), "arbeitgeber", "name")
);
Sample Output
Before and after edit snapshots:
Sample code
TableViewTest.java
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableViewTest extends Application {
private TableView<Arbeitgeber> arbeitgeberTable;
private TableView<Person> personTable;
ObservableList<String> gruppeOptions =
FXCollections.observableArrayList(
"Arbeiter",
"Angestellter",
"Leiter"
);
private ObservableList<Arbeitgeber> arbeitgeberListe = FXCollections.observableArrayList(new Arbeitgeber(1, "Goldgräber Inc."), new Arbeitgeber(2, "Hamster GmbH"), new Arbeitgeber(3, "Wissen"));
private ObservableList<Person> personen = FXCollections.observableArrayList(
new Person(1, "Max Musterman", gruppeOptions.get(1), arbeitgeberListe.get(0)),
new Person(2, "Bernd Brot", gruppeOptions.get(0), arbeitgeberListe.get(0)),
new Person(3, "Fred Feuer", gruppeOptions.get(2), arbeitgeberListe.get(1)),
new Person(4, "Uli Stein", gruppeOptions.get(1), arbeitgeberListe.get(2)));
#Override
public void start(Stage primaryStage) throws Exception {
createArbeitgeberTableview();
createPersonTableview();
VBox vbox = new VBox(15);
Label aLabel = new Label("Arbeitgeber");
Label pLabel = new Label("Personen");
vbox.getChildren().addAll(aLabel, arbeitgeberTable, pLabel, personTable);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args
*/
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private TableView<Arbeitgeber> createArbeitgeberTableview() {
arbeitgeberTable = new TableView<>(arbeitgeberListe);
arbeitgeberTable.setEditable(true);
TableColumn<Arbeitgeber, Integer> idCol = new TableColumn<>("ID");
TableColumn nameCol = new TableColumn<>("Name");
idCol.setCellValueFactory(new PropertyValueFactory<Arbeitgeber, Integer>("id"));
nameCol.setCellValueFactory(new PropertyValueFactory<Arbeitgeber, String>("name"));
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
nameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Arbeitgeber,String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Arbeitgeber, String> event) {
((Arbeitgeber) event.getTableView().getItems().get(event.getTablePosition().getRow())).setName(event.getNewValue());
for(Person p : personTable.getItems()) {
System.out.println(p.getArbeitgeber()); //shows the new value
}
}
});
arbeitgeberTable.getColumns().addAll(idCol, nameCol);
arbeitgeberTable.setTableMenuButtonVisible(true);
return arbeitgeberTable;
}
#SuppressWarnings("unchecked")
private TableView<Person> createPersonTableview(){
personTable = new TableView<>(personen);
TableColumn<Person, Integer> idCol = new TableColumn<>("ID");
TableColumn<Person, String> nameCol = new TableColumn<>("Name");
TableColumn<Person, String> gruppeCol = new TableColumn<>("Gruppe");
TableColumn<Person, String> arbCol = new TableColumn<>("Arbeitgeber");
idCol.setCellValueFactory(new PropertyValueFactory<Person, Integer>("id"));
nameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
gruppeCol.setCellValueFactory(new PropertyValueFactory<Person, String>("gruppe"));
arbCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> p) {
return Bindings.selectString(
new ReadOnlyObjectWrapper<Object>(
p.getValue()
),
"arbeitgeber", "name"
);
}
});
personTable.getColumns().addAll(idCol, nameCol, gruppeCol, arbCol);
personTable.setTableMenuButtonVisible(true);
return personTable;
}
}
Person.java
import javafx.beans.property.*;
public class Person {
private IntegerProperty id = new SimpleIntegerProperty();
private StringProperty name = new SimpleStringProperty();
private StringProperty gruppe = new SimpleStringProperty();
private ObjectProperty<Arbeitgeber> arbeitgeber = new SimpleObjectProperty<>();
public Person(int id, String name, String gruppe, Arbeitgeber arbeitgeber) {
setId(id);
setName(name);
setGruppe(gruppe);
setArbeitgeber(arbeitgeber);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public String getGruppe() {
return gruppe.get();
}
public StringProperty gruppeProperty() {
return gruppe;
}
public void setGruppe(String gruppe) {
this.gruppe.set(gruppe);
}
public Arbeitgeber getArbeitgeber() {
return arbeitgeber.get();
}
public ObjectProperty<Arbeitgeber> arbeitgeberProperty() {
return arbeitgeber;
}
public void setArbeitgeber(Arbeitgeber arbeitgeber) {
this.arbeitgeber.set(arbeitgeber);
}
#Override
public String toString() {
return "Person{" +
"id=" + id +
", name=" + name +
", gruppe=" + gruppe +
", arbeitgeber=" + arbeitgeber +
'}';
}
}
Arbeitgeber.java
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Arbeitgeber {
private IntegerProperty id = new SimpleIntegerProperty();
private StringProperty name = new SimpleStringProperty();
public Arbeitgeber(int id, String name) {
setId(id);
setName(name);
}
public IntegerProperty idProperty() {
return id;
}
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
public StringProperty nameProperty() {
return name;
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
#Override
public String toString() {
return "Arbeitgeber{" +
"id=" + id +
", name=" + name +
'}';
}
}

Categories