How to set value to cell in TableView in javafx - javafx

I am newbie on javafx. I already code in core java to set value to table. But now i am converting my project in javafx to maintain code and to improve design.
I am trying to set value to table view but i am not getting how to set value to tableview.
Here is my code which i am using for swing.
String testbedName = treePath.getPathComponent(1).toString();
TestBed currentTestbed = getTbF().get(testbedName);
propertyTable.getModel().setValueAt(currentTestbed.getTestBedName(), 0, 1);
propertyTable.getModel().setValueAt(currentTestbed.getTestBedFilePath() + "\\" + testbedName + ".xml", 1, 1);
propertyTable.getModel().setValueAt(currentTestbed.getTbElements().size(), 2, 1);
But i need to convert this code in javafx means from JTable to TableView. but tableview not find getModel() method.
I search but didn't get how to set value to table view.
Please give me reference or hint.
Thanks in advance.

In JavaFX you generally don't set the values cell by cell like that. In your case, for example, you would
place your TestBeds in the table:
TableView<TestBed> table = new TableView<>();
table.getItems().addAll(yourTestBeds);
you then create the columns you need, by providing appropriate cell value factories, for example (using Java 8 syntax):
TableColumn<TestBed, String> name = new TableColumn<>();
name.setCellValueFactory(c-> new SimpleStringProperty(c.getValue().getTestBedName()));
If you use Java 7:
name.setCellValueFactory(new Callback<CellDataFeatures<TestBed, String>, ObservableValue<String>>() {
#Override public ObservableValue<String> call(CellDataFeatures<TestBed, String> c) {
return new SimpleStringProperty(c.getValue().getTestBedName()));
}
});
Finally you add the columns to the table:
table.getColumns().addAll(name, someOtherColumn);

Suppose we have a table with two columns, one for a string, the other for a number. To set programmatically the i-th item or row of the table, we can do like this:
//Define the string
String s = "myString" ;
//Define the number
int value = 5;
//Synthesize the item = row
Item item = new Item(s, value);
//Set the i-th item
table.getItems().set(i, item);

Related

Javafx tableview column value from event handler

Is it possible to take a value of table column from a event handler in Javafx?
The task is I need to click a button, calculate functions, and return the value to the column.
I have this working:
data.add(new Person(id, name));
I have this:
TableColumn nameCol = new TableColumn ("name");
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
// And id as well.
TableColumn resultsCol = new TableColumn ("Results");
resultsCol.setCellValueFactory(new PropertyValueFactory<>("results"));
And this:
add.setOnAction (e -> {
// I don't know what to put
});
Because id and name column are already working, what should I do to separately add a new value to the column from a button?
Because your CellValueFactories are pulling values directly from your Person object you would need to update the variables in the particular row's Person object when your button is clicked. You can do this with simple setter methods.
You could also use a technique like this to create a table with cells that can be edited with a click: http://java-buddy.blogspot.com/2012/04/javafx-2-editable-tableview.html?m=1
I have successfully implemented this technique in my applications.

Javafx getting the new value of a cell that is changed in a tableview

I've made an editable cell in my javafx table using http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm#CJAGAAEE, but whatever I try I cannot get the new value. Instead I always get the value in the first column using
firstNameCol.setOnEditCommit(
(CellEditEvent<Person, String> t) -> {
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setFirstName(t.getNewValue());
});
(The code example in the link above)
My code is large, its my project but roughly my code so far for this section is.
timeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
timeColumn.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
#Override
public void handle(TableColumn.CellEditEvent event) {
tableView.getItems().get(event.getTablePosition().getRow());
}
});
I am editing a cell in row 1, column 2 but for some reason it is always returning the object in row 1 column 1 and not the new value in row 1 column 2.
Any advice?
I've event tried
tableView.getItems().get(event.getTablePosition().getRow()) + 1;
But this did not work
Based on #James_D comment above. If you want to get the first column's value then just do
column2.setOnEditCommit( e -> {
//here you can get the value of column1 corresponding to column2
System.out.println(e.getRowValue().getColumn1());
});
This should help you get the correct person.
TableView tempTable = (TableView)event.getTableView();
Person tempPerson = (Person)tempTable.getItems().get(event.getTablePosition().getRow());
tempPerson.setYourMethod(event.getNewValue());//maybe toString?
If your object is not a Person object, then replace Person with your object type.

javaFx TableView with Multiple ComboBoxes

I have a requirement where in i am supposed to compare two csv files. For comparison , we are trying to implement a rules configuration. Now the Rules will have an object like the following :
public class CsvInformation {
private String resultType;
private List<String> primaryKey;
private List<String> standardKey;
private List<String> ignoreKey;
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public List<String> getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(List<String> primaryKey) {
this.primaryKey = primaryKey;
}
public List<String> getStandardKey() {
return standardKey;
}
public void setStandardKey(List<String> standardKey) {
this.standardKey = standardKey;
}
public List<String> getIgnoreKey() {
return ignoreKey;
}
public void setIgnoreKey(List<String> ignoreKey) {
this.ignoreKey = ignoreKey;
}
so i am fetching a list of CSVInformation objects.Now i'd like to map/bind these to a tableView control so that the user will get an option to select values for PrimaryKey,IgnoreKey,StandardKey through a comboBox control in a TableView Cell. The TableView Control should look something similar to the following snapshot.
In the snapshot above, i'd like to fill each row of the TableView with each object of the List of CsvInformation Objects which i am getting from the backEnd. Is this achievable . I googled a bit but everywhere they have mentioned they haven't been able to use a Collection for binding to a comboBox inside a TableView . Any advice/ pointers/ suggestion will be highly appreciated. Thanks
#James_D : Hi James, Thx for the reply. The primary idea is that the user will be given the optoin to select primary Key,Standard Key & Ignore Key so as to tell us which columns to include for comparison and which ones to ignore , which is the primary key etc. Once the user makes that selection for as many rows as are present in the TableView at that time, i need to save these and create a Json out of that.The requirement is such that the tableView needs to comprise of 4 columns : 1 label, 3 Non- Editable Combo-boxes. Now to answer your query on combo box, each combo-box will be unique in nature i.e the entries that'll fill the ComboBox inside the TableView, if i say Row 1 , primaryKey Combo - box will have String values such as Mohit,Neha,Neeraj. Now when i move to fill the fill the next row, i.e Row 2 primaryKey Combo - box will have values such as James,Jason,Bourne.What i am trying to achieve is to create these combo-boxes on the go by binding to a list. I'm attaching a snapshot here for the content of csvHeaderList.Each row in the TableView Content will be from each ondex of the CSVHeaderList. Please let me know if you need any more insights on this.
< TabelView code >
TableView<CsvInformation > table = new TableView<CsvInformation >();
// Create column Result Type (Data type of String).
TableColumn<CsvInformation , String> resultTypeCol = new TableColumn<CsvInformation , String>("Result Type");
// Create column Primary Column (Data type of List<String>).
TableColumn<CsvInformation , List<String>> primaryKeyCol = new TableColumn<CsvInformation , List<String>>("Primary Column");
// Create column Standard Column (Data type of List<String>).
TableColumn<CsvInformation , List<String>> standardCol = new TableColumn<CsvInformation , List<String>>("Standard Column");
// Create column for Ignorable Columns. (Data type of List<String>).
TableColumn<CsvInformation , List<String>> ignoredCol = new TableColumn<CsvInformation , List<String>>("Ignorable Columns");
PropertyValueFactory<CsvInformation , List<CsvInformation >> resultTypeColFactory = new PropertyValueFactory<>(
"resultType");
PropertyValueFactory<CsvInformation , List<CsvInformation >> primaryColFactory = new PropertyValueFactory<>(
"primaryKey");
PropertyValueFactory> standardColFactory = new PropertyValueFactory<>(
"standardKey");
PropertyValueFactory> compareColFactory = new PropertyValueFactory<>(
"ignoreKey");
// Defines how to fill data for each cell.
// Get value from property of CsvInformation.
resultTypeCol.setCellValueFactory(new PropertyValueFactory<>("resultType"));
primaryKeyCol.setCellValueFactory(new PropertyValueFactory<>("primaryKey"));
standardCol.setCellValueFactory(new PropertyValueFactory<>("standardKey"));
ignoredCol.setCellValueFactory(new PropertyValueFactory<>("ignoreKey"));
Where i'm stuck is how to provide my definition for Tablecolumn,Table Cell,Cellfactory for a collection / List like :
TableColumn for mapping my list to a combobox inside a TableView.

Can't clear all items (elements) in an ObservableList

I've a couple of copied elements in an observablelist which I use for copy/paste operations in a TableView. The name of the table is cpTable (copy and paste Table) for storing copied elements and to paste elements that are stored in the table. After each paste operation I want to clear the contents of cpTable before I copy other selected items with Ctrl+C.
But I always get the error:
JavaFX Application Thread" java.lang.UnsupportedOperationException:
Not supported.
at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.remove(ReadOnlyUnbackedObservableList.java:246)
Here is my pseudocode:
if (cpTable !=null) {
//first, get all copied items for removing all elements
ObservableList<String> copiedItems = cpTable.getItems();
int size = copiedItems.size();
// remove all elements
for(int i=0;i<size;i++) {
copiedItems.remove(i);
}
cpTable.setItems(copiedItems); //clear cpTable by setting an empty list
}
This is a method that copies the contents of selected items and puts it in a cpTable
public TableView<String> copySelectionToClipboard(TableView<String> table) {
ObservableList<String> data = table.getSelectionModel().getSelectedItems();
TableView<String> tmp = new TableView<>();
tmp.setItems(data);
return tmp;
}
When Ctrl+C is pressed the following line puts all copied items in a cpTable:
cpTable = copySelectionToClipboard( (TableView<String>) keyEvent.getSource());
As mentioned I want to clear all cpTable contents immediately after pasting
the items in a table.
Just clear your Observable List. It looks like you should use copiedItems.clear();
That should clear your table.
As James_D already mentioned, you haven't cleared exactly what's the point.
If you want to delete selected items from a table, you need to delete them from the table item list itself and not from the selection model.
A possible solution looks like this:
TableView<String> table = new TableView<>();
ObservableList<String> tableItems = table.getItems();
// needs multirowselection is set to true
ObservableList<String> readOnlyItems = table.getSelectionModel().getSelectedItems();
// removes all selected elements for the table
readOnlyItems.stream().forEach((item) -> {
tableItems.remove(item);
});
// clear the selection
table.getSelectionModel().clearSelection();
Update
This method get's an TableView, calls it's selection model to get all selected items. And then you add the data to a new TableView. And there is the problem! It's an unmodifiable read only list that you attached to your new table. First make it modifiable, like in the code below:
public TableView<String> copySelectionToClipboard(TableView<String> table) {
ObservableList<String> readOnlyData = table.getSelectionModel().getSelectedItems();
ObservableList<String> writableData = FXCollections.<String>observableArrayList(readOnlyData);
TableView<String> tmp = new TableView<>();
tmp.setItems(writableData);
return tmp;
The next problem is in your call to this method. You call it with a TableView<CsvData> and with a TableView<String> as your method needs. If CsvData is a subtype of String, than you have to change your method signature to TableView<? extends String>
If you are trying to clear all the items from your tableView and want just an empty tableView. You can use this:
myTableView.getItems().clear();
This basically gets all the items from your table view which is nothing but just the observable list now it performs clear operations to remove all the items in tableView.
Assuming you mean
table.getSelectionModel().getSelectedItems()
(since the selection model has no getItems() method), according to the Javadocs, this returns a read-only list. Thus attempting to modify the list will throw an UnsupportedOperationException.
To clear the selection, do
table.getSelectionModel().clearSelection();
(And similarly, if you want to manipulate the selection in any other way, you use methods on the selection model, rather than on the list.)

JavaFX architecture in building dynamic "rows"

I have an application that I am building that has a table in it, I'm not using a tableview to build this table because I need each row to be able to expand similar to an accordion. I was able to achieve what I need by using a timeline and looping through the data and building each row (its kind of crude right now since I'm still working with dummy data eventually it will be a list iterator and not just a for loop) but I'm not happy with how its done. There are a lot of default values that will never change so I don't really need to set them in my worker class every time, I decided to just add them to the object class that I put together. So basically, at a high level it looks something like this:
for (int i = 0; i < 30; i++) {
RowBuilder builder = new RowBuilder(tableBox, i);
try {
builder.run();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm passing it the parent which is a VBox - tableBox, then I'm passing the count for later use.
Inside the RowBuilder I'm getting a new instance of the object DashboardRow which has all the defaults set in it, then I'm setting the data for each row and returning the DashboardRow.
Here is an example of a getter setting values in the DashboardRow
public HBox getMainRow() {
mainRow.setAlignment(Pos.CENTER_LEFT);
mainRow.setPrefHeight(60);
mainRow.setMinHeight(60);
mainRow.setMaxHeight(60);
mainRow.setPrefWidth(-1);
mainRow.setStyle("-fx-background-color:#FFFFFF;");
return mainRow;
}
Inside the DashboardRow class I have a ton of new objects being created for every element I need in the row. There are 21 for each row, mostly VBox, HBox and StackPane to build the actual row, the rest are just labels and buttons.
This is what is looks like so far. Opened and closed states.
Is there a better way to dynamically build things like this in javafx? I'm basically pulling data from a database and looping through that data to populate a row.
I can't comment but it may be an answer anyway. Why can't you use the setGraphic method of a custom table cell and put the accordion node in a table. setGraphic takes any kind of node.
It sounds simpler than what you're doing.
I just tried it out with the Oracle sample and it works great.
I added
Callback<TableColumn<Person, String>, TableCell<Person, String>> accCellFactory
= new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
#Override
public TableCell call(TableColumn p) {
TitledPane t1 = new TitledPane("T1", new Button("B1"));
TitledPane t2 = new TitledPane("T2", new Button("B2"));
TitledPane t3 = new TitledPane("T3", new Button("B3"));
Accordion accordion = new Accordion();
accordion.getPanes().addAll(t1, t2, t3);
TableCell tc = new TableCell();
tc.setGraphic(accordion);
return tc;
}
};
and changed this line firstNameCol.setCellFactory(accCellFactory);
and I get
Of course you might want something other than buttons but I just copied the Accordion sample from the javadoc.

Resources