This example not work correctly when compile with JDK 1.8/JavaFX 8. Please read: http://goo.gl/IRCaz4
To get individual record in a TableView, using the code:
Record selectedRecord = (Record)tableView.getItems().get(selectdIndex);
where selectedIndex is the index in the TableView interested.
Extend from last article of "Embed Button in TableView", implement EventHandler of the embedded button, th read data of the selected row and display on another TableView within dialog.
Get row data from TableView |
package javafxdyntable; import java.util.Random; import javafx.application.Application; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleStringProperty; 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.geometry.Pos; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.chart.XYChart; import javafx.scene.control.Button; import javafx.scene.control.ContentDisplay; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.VBox; import javafx.scene.layout.VBoxBuilder; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.util.Callback; /** * @web http://java-buddy.blogspot.com/ */ public class JavaFXDynTable extends Application { private TableView tableView = new TableView(); private Button btnNew = new Button("New Record"); static Random random = new Random(); static final String Day[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}; public static class Record { private final SimpleIntegerProperty id; private final SimpleIntegerProperty value_0; private final SimpleIntegerProperty value_1; private final SimpleIntegerProperty value_2; private final SimpleIntegerProperty value_3; private final SimpleIntegerProperty value_4; Record(int i, int v0, int v1, int v2, int v3, int v4) { this.id = new SimpleIntegerProperty(i); this.value_0 = new SimpleIntegerProperty(v0); this.value_1 = new SimpleIntegerProperty(v1); this.value_2 = new SimpleIntegerProperty(v2); this.value_3 = new SimpleIntegerProperty(v3); this.value_4 = new SimpleIntegerProperty(v4); } public int getId() { return id.get(); } public void setId(int v) { id.set(v); } public int getValue_0() { return value_0.get(); } public void setValue_0(int v) { value_0.set(v); } public int getValue_1() { return value_1.get(); } public void setValue_1(int v) { value_1.set(v); } public int getValue_2() { return value_2.get(); } public void setValue_2(int v) { value_2.set(v); } public int getValue_3() { return value_3.get(); } public void setValue_3(int v) { value_3.set(v); } public int getValue_4() { return value_4.get(); } public void setValue_4(int v) { value_4.set(v); } }; ObservableList<Record> data = FXCollections.observableArrayList(); @Override public void start(final Stage primaryStage) { primaryStage.setTitle("java-buddy.blogspot.com"); tableView.setEditable(true); Callback<TableColumn, TableCell> cellFactory = new Callback<TableColumn, TableCell>() { @Override public TableCell call(TableColumn p) { return new EditingCell(); } }; btnNew.setOnAction(btnNewHandler); //init table //Un-editable column of "id" TableColumn col_id = new TableColumn("ID"); tableView.getColumns().add(col_id); col_id.setCellValueFactory( new PropertyValueFactory<Record, String>("id")); //Editable columns for(int i=0; i<Day.length; i++){ TableColumn col = new TableColumn(Day[i]); col.setCellValueFactory( new PropertyValueFactory<Record, String>( "value_" + String.valueOf(i))); tableView.getColumns().add(col); col.setCellFactory(cellFactory); } //Insert Button TableColumn col_action = new TableColumn<>("Action"); col_action.setSortable(false); col_action.setCellValueFactory( new Callback<TableColumn.CellDataFeatures<Record, Boolean>, ObservableValue<Boolean>>() { @Override public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Record, Boolean> p) { return new SimpleBooleanProperty(p.getValue() != null); } }); col_action.setCellFactory( new Callback<TableColumn<Record, Boolean>, TableCell<Record, Boolean>>() { @Override public TableCell<Record, Boolean> call(TableColumn<Record, Boolean> p) { return new ButtonCell(tableView); } }); tableView.getColumns().add(col_action); tableView.setItems(data); Group root = new Group(); VBox vBox = new VBox(); vBox.setSpacing(10); vBox.getChildren().addAll(btnNew, tableView); root.getChildren().add(vBox); primaryStage.setScene(new Scene(root, 600, 400)); primaryStage.show(); } public static void main(String[] args) { launch(args); } public class SubRecord{ private SimpleStringProperty fieldSubRecordName; private SimpleIntegerProperty fieldSubRecordValue; SubRecord(String sn, int sv){ this.fieldSubRecordName = new SimpleStringProperty(sn); this.fieldSubRecordValue = new SimpleIntegerProperty(sv); } public String getFieldSubRecordName() { return fieldSubRecordName.get(); } public int getFieldSubRecordValue() { return fieldSubRecordValue.get(); } } //Define the button cell private class ButtonCell extends TableCell<Record, Boolean> { final Button cellButton = new Button("Action"); ButtonCell(final TableView tblView){ cellButton.setOnAction(new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent t) { int selectdIndex = getTableRow().getIndex(); //Create a new table show details of the selected item Record selectedRecord = (Record)tblView.getItems().get(selectdIndex); ObservableList<SubRecord> subDataList = FXCollections.observableArrayList( new SubRecord("ID", selectedRecord.getId()), new SubRecord("Monday", selectedRecord.getValue_0()), new SubRecord("Tuesday", selectedRecord.getValue_1()), new SubRecord("Wednesday", selectedRecord.getValue_2()), new SubRecord("Thursday", selectedRecord.getValue_3()), new SubRecord("Friday", selectedRecord.getValue_4())); TableColumn columnfield = new TableColumn("Field"); columnfield.setCellValueFactory( new PropertyValueFactory<Record,String>("fieldSubRecordName")); TableColumn columnValue = new TableColumn("Value"); columnValue.setCellValueFactory( new PropertyValueFactory<SubRecord,Integer>("fieldSubRecordValue")); TableView<SubRecord> subTableView = new TableView<>(); subTableView.setItems(subDataList); subTableView.getColumns().addAll(columnfield, columnValue); Stage myDialog = new Stage(); myDialog.initModality(Modality.WINDOW_MODAL); Scene myDialogScene = new Scene(VBoxBuilder.create() .children(subTableView) .alignment(Pos.CENTER) .padding(new Insets(10)) .build()); myDialog.setScene(myDialogScene); myDialog.show(); } }); } //Display button if the row is not empty @Override protected void updateItem(Boolean t, boolean empty) { super.updateItem(t, empty); if(!empty){ setGraphic(cellButton); } } } EventHandler<ActionEvent> btnNewHandler = new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent t) { //generate new Record with random number int newId = data.size(); Record newRec = new Record( newId, random.nextInt(100), random.nextInt(100), random.nextInt(100), random.nextInt(100), random.nextInt(100)); data.add(newRec); } }; class EditingCell extends TableCell<XYChart.Data, Number> { private TextField textField; public EditingCell() {} @Override public void startEdit() { super.startEdit(); if (textField == null) { createTextField(); } setGraphic(textField); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); textField.selectAll(); } @Override public void cancelEdit() { super.cancelEdit(); setText(String.valueOf(getItem())); setContentDisplay(ContentDisplay.TEXT_ONLY); } @Override public void updateItem(Number item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (isEditing()) { if (textField != null) { textField.setText(getString()); } setGraphic(textField); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } else { setText(getString()); setContentDisplay(ContentDisplay.TEXT_ONLY); } } } private void createTextField() { textField = new TextField(getString()); textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()*2); textField.setOnKeyPressed(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent t) { if (t.getCode() == KeyCode.ENTER) { commitEdit(Integer.parseInt(textField.getText())); } else if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); } } }); } private String getString() { return getItem() == null ? "" : getItem().toString(); } } }
Where is the code for getTableRow()?
ReplyDeletehttp://docs.oracle.com/javafx/2/api/javafx/scene/control/TableCell.html#getTableRow()
Deletevery informative, as always!
ReplyDeleteyou have one of the best javafx tutorial pages (if not the best) around.
Thanks for giving solution for my project.....
ReplyDeletehow to add tablecolumn in
ReplyDeleteHello,
ReplyDeleteI think there is a problem with this tutorial. The class values are not affected by any element modification in the TableView. When the action button is clicked, the old values are displayed.
Thank you for all these so interesting tutorials.
Anthony_B,
DeleteYou are right, I missed handle of col.setOnEditCommit.
But I found more problem when compile with JDK 1.8/JavaFX 8!
please read: http://goo.gl/IRCaz4
Is there any way we can update the database through JavaFx. Like import the table and update it dynamically into database
ReplyDelete