Cant see data in cells in tableview after setItems() [duplicate] - java

This question already has answers here:
Javafx tableview not showing data in all columns
(3 answers)
Closed 3 years ago.
I am trying to put my test ObservableList data into JavaFX TableView i made with scene builder, but when i use setItems() i can see there are 5 rows of data, but cells in that row dont contain any data or at least i cant see it
private final ObservableList<tblQuery> data =
FXCollections.observableArrayList(
new tblQuery("Jacob", "Smith", "jacob.smith#example.com"),
//4 more rows
);
private javafx.scene.control.TableView<tblQuery> tableview;
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
tableview = (TableView) loader.getNamespace().get("tabQuery");
primaryStage.setTitle("Cycle reloader");
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root));
tableview.setEditable(true);
TableColumn coID = new TableColumn("Cycle№");
coID.setMinWidth(80);
coID.setCellValueFactory(
new PropertyValueFactory<tblQuery, String>("id"));
//workflow and date columns, same as id column
tableview.setItems(data);
tableview.getColumns().addAll(coID, colWorkflow, colDate);
primaryStage.show();
}
public class tblQuery {
private final SimpleStringProperty id;
private final SimpleStringProperty workflow;
private final SimpleStringProperty date;
private tblQuery(String id, String workflow, String date) {
this.id = new SimpleStringProperty(id);
this.workflow = new SimpleStringProperty(workflow);
this.date = new SimpleStringProperty(date);
}
public String getID() {
return id.get();
}
public void setID(String fName) {
id.set(fName);
}
public String getWorkflow() {
return workflow.get();
}
public void setWorkflow(String fName) {
workflow.set(fName);
}
public String getDate() {
return date.get();
}
public void setDate(String fName) {
date.set(fName);
}
}
and all i can see is:
i can select any row above selected, but cant go down with selection

getID() is misspelled. It is suppose to be getId() in order to follow the bean convention.
Here is modified working example.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
public class TableApp extends Application {
private final ObservableList<TblQuery> data =
FXCollections.observableArrayList(
new TblQuery("Jacob", "Smith", "jacob.smith#example.com"),
new TblQuery("Isabella", "Johnson", "isabella.johnson#example.com"),
new TblQuery("Ethan", "Williams", "ethan.williams#example.com"),
new TblQuery("Emma", "Jones", "emma.jones#example.com"),
new TblQuery("Michael", "Brown", "michael.brown#example.com")
);
private javafx.scene.control.TableView<TblQuery> tableview = new TableView<>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Cycle reloader");
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(tableview));
tableview.setEditable(true);
TableColumn idCol = new TableColumn("What");
idCol.setMinWidth(80);
idCol.setCellValueFactory(
new PropertyValueFactory<TblQuery, String>("id"));
TableColumn workflowCol = new TableColumn("Workflow name");
workflowCol.setMinWidth(236);
workflowCol.setCellValueFactory(
new PropertyValueFactory<TblQuery, String>("workflow"));
TableColumn dateCol = new TableColumn("AS OF DAY");
dateCol.setMinWidth(80);
dateCol.setCellValueFactory(
new PropertyValueFactory<TblQuery, String>("date"));
tableview.setItems(data);
tableview.getColumns().addAll(idCol, workflowCol, dateCol);
primaryStage.show();
}
}
import javafx.beans.property.SimpleStringProperty;
public class TblQuery {
private final SimpleStringProperty idProperty = new SimpleStringProperty();
private final SimpleStringProperty workflowProperty = new SimpleStringProperty();
private final SimpleStringProperty dateProperty = new SimpleStringProperty();
public TblQuery(String id, String workflow, String date) {
this.idProperty.set(id);
this.workflowProperty.set(workflow);
this.dateProperty.set(date);
}
public void setId(String id) {
this.idProperty.set(id);
}
public String getId() {
return idProperty.get();
}
public String getWorkflow() {
return workflowProperty.get();
}
public void setWorkflow(String workflow) {
this.workflowProperty.set(workflow);
}
public String getDate() {
return dateProperty.get();
}
public void setDate(String date) {
this.dateProperty.set(date);
}
}

Related

I'm not able to access variables used in GUI (lambda expression)from other class

I'm making a gui application using javafx that takes input from user and then computes that data in other class. I've tried making an object and accessing it but can't get it to work. I've googled and tried a lot of things like using abstract method but can't get it to work. please tell how can i access the variables( like ID,Party,VoterAge) from controller class or any other class
Submit.setOnAction((ActionEvent e) -> {
primaryStage.setScene(scene1);
String ID = VoterIdtext.getText();
String Party=VoteTotext.getText();
Integer VoterAge=Integer.parseInt(Agetext.getText());
}
As can be seen from your example, your variables (ID, Party, VoterAge) are described into the method and they are local variables.
When you want to use them in other classes you need to declare them in other part. For example:
public static String ID = "";
public static String Party;
public static int VoterAge = null;
...
Submit.setOnAction((ActionEvent e) -> {
primaryStage.setScene(scene1);
ID = VoterIdtext.getText();
Party=VoteTotext.getText();
VoterAge=Integer.parseInt(Agetext.getText());
}
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SampleApp extends Application {
public class Info {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = Integer.parseInt(age);
}
}
private TextField ageField;
private TextField nameField;
private Info info;
private Button printButton;
private Button submitButton;
#Override public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
primaryStage.setScene(new Scene(root));
createNameField(root);
createAgeField(root);
submitButton = new Button("Submit");
submitButton.setOnAction((e) -> setInfo());
ButtonBar e = new ButtonBar();
printButton = new Button("Print Info");
printButton.setDisable(true);
printButton.setOnAction((eve) -> printInfo());
e.getButtons().addAll(submitButton, printButton);
root.getChildren().add(e);
primaryStage.show();
}
private void printInfo() {
System.out.println("Name: " + info.getName());
System.out.println("Age: " + info.getAge());
}
private void setInfo() {
info = new Info();
info.setName(nameField.getText());
info.setAge(ageField.getText());
printButton.setDisable(false);
}
private void createAgeField(VBox root) {
HBox ageBox = new HBox(10);
root.getChildren().add(ageBox);
ageField = new TextField();
ageBox.getChildren().addAll(new Label("Age: "), ageField);
}
private void createNameField(VBox root) {
HBox ageBox = new HBox();
root.getChildren().add(ageBox);
nameField = new TextField();
ageBox.getChildren().addAll(new Label("Name: "), nameField);
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX property adapter for TableView

For DTO I use POJO. So to make bidirectional binding I create adapter. I mean, something like that:
POJO:
public class Temp{
private BigDecimal weight;
private final PropertyChangeSupport propertyChangeSupport;
public Temp() {
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
BigDecimal pv = this.weight;
this.weight = weight;
propertyChangeSupport.firePropertyChange("weight", pv, weight);
}
}
I have the following adapter:
public class TempAdapter {
private ObjectProperty<BigDecimal> weightProperty;
public TempAdapter(Temp temp) {
try {
weightProperty=new JavaBeanObjectPropertyBuilder<BigDecimal>().bean(temp).name("weight").build();
weightProperty.addListener(new ChangeListener<BigDecimal>() {
#Override
public void changed(ObservableValue<? extends BigDecimal> ov, BigDecimal t, BigDecimal t1) {
....
}
});
} catch (NoSuchMethodException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
}
public ObjectProperty<BigDecimal> getWeightProperty() {
return weightProperty;
}
However, I can't understand how to use this adapter with TableView. The reason I want to use adapter for TableView is that otherwise we will have to duplicate the code of the adapter in TableView if we using POJO for DTO with TableView.
As I understand for every row in TableView we must create a new Instance of Adapter and I can't understand how to do it.
Solution without an adapter class
First note you don't necessarily need an adapter class; you can just create the JavaBeanProperty instances where you need them: in this case in the cell value factory for the table. If there is just one (or perhaps two) places in the UI where you need to bind directly to a JavaFX Property corresponding to properties in your POJO, then this is probably the way to go.
Here's a complete example of this technique, using the usual Oracle Person table example. In this example, there is no adapter class: the table just creates the JavaBeanStringProperty adapters in the cell value factory. There is an edit form, which just interacts with the POJO class directly.
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.application.Application;
import javafx.beans.property.adapter.JavaBeanStringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.setEditable(true);
TableColumn<Person, String> firstNameColumn = createColumn("First Name", "firstName");
TableColumn<Person, String> lastNameColumn = createColumn("Last Name", "lastName");
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
Button button = new Button("Show data");
button.setOnAction(e -> {
table.getItems().stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
table.getItems().addAll(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(Person person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField(person.getFirstName());
TextField lastNameField = new TextField(person.getLastName());
Button okButton = new Button("OK");
Button cancelButton = new Button("Cancel");
HBox buttons = new HBox(10, okButton, cancelButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
cancelButton.setOnAction(e -> stage.hide());
okButton.setOnAction(e -> {
person.setFirstName(firstNameField.getText());
person.setLastName(lastNameField.getText());
stage.hide();
});
stage.show();
}
private TableColumn<Person, String> createColumn(String title, String property) {
TableColumn<Person, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> {
Person p = cellData.getValue();
try {
JavaBeanStringProperty prop = new JavaBeanStringPropertyBuilder()
.bean(p)
.name(property)
.build();
return prop;
} catch (Exception e) {
throw new RuntimeException(e);
}
});
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static void main(String[] args) {
launch(args);
}
}
Solution using an adapter class
Note that in the above example, the text fields in the editor can't use bindings directly with the POJO class (because it doesn't expose any JavaFX properties); if you wanted to do so you could create more JavaBeanStringPropertys for the purpose, but that would end up duplicating code. If you wanted to be able to do this, then it might become beneficial to use an adapter class. Here is what the code might look like using this solution. Note that now the adapter class exposes JavaFX properties, so the table's cell value factory can just map directly to those properties: the creation of the JavaBeanStringPropertys is encapsulated in one place (the adapter class):
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
#Override
public void start(Stage primaryStage) {
TableView<PersonAdapter> table = new TableView<>();
table.setEditable(true);
TableColumn<PersonAdapter, String> firstNameColumn = createColumn("First Name", PersonAdapter::firstNameProperty);
TableColumn<PersonAdapter, String> lastNameColumn = createColumn("Last Name", PersonAdapter::lastNameProperty);
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
List<Person> data = Arrays.asList(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
Button button = new Button("Show data");
button.setOnAction(e -> {
data.stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
data.stream().map(PersonAdapter::new).forEach(table.getItems()::add);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(PersonAdapter person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField();
firstNameField.textProperty().bindBidirectional(person.firstNameProperty());
TextField lastNameField = new TextField();
lastNameField.textProperty().bindBidirectional(person.lastNameProperty());
Button okButton = new Button("OK");
HBox buttons = new HBox(10, okButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
okButton.setOnAction(e -> {
stage.hide();
});
stage.show();
}
private TableColumn<PersonAdapter, String> createColumn(String title, Function<PersonAdapter, StringProperty> property) {
TableColumn<PersonAdapter, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static class PersonAdapter {
private final Person person ;
private final StringProperty firstName ;
private final StringProperty lastName ;
public PersonAdapter(Person person) {
this.person = person ;
try {
this.firstName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("firstName")
.build();
this.lastName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("lastName")
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Person getPerson() {
return person ;
}
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 static void main(String[] args) {
launch(args);
}
}
The one possible disadvantage to this approach is that changes to the underlying list (data in the simple example) will not propagate to the table (this means adding or removing elements from data will not change the table; calling setFirstName or setLastName on the existing elements of the table will allow for updates). For techniques to manage this, see Best practice to decorate an ObservableList and retain change events

how to change final value of StringProperty type in javaFX?

i was trying to learn Tableview and got some example.
i dont get how StringProperty works.
Although class Person's fields are final instanace,
setEmailButton can change its value.
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.event.*;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class PropertyBasedTableView extends Application {
private TableView<Person> table = new TableView<Person>();
private final ObservableList<Person> data = FXCollections.observableArrayList();
private void initData() {
data.setAll(
new Person("Jacob", "Smith", "jacob.smith#example.com"),
new Person("Isabella", "Johnson", "isabella.johnson#example.com"),
new Person("Ethan", "Williams", "ethan.williams#example.com")
);
}
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) {
initData();
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 firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn emailCol = new TableColumn("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
table.setPrefHeight(300);
final Button setEmailButton = new Button("Set first email in table to wizard#frobozz.com");
setEmailButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
if (data.size() > 0) {
data.get(0).setEmail("wizard#frobozz.com");
}
}
});
final VBox vbox = new VBox(10);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, setEmailButton);
stage.setScene(new Scene(new Group(vbox)));
stage.show();
}
public static class Person {
private final StringProperty firstName;
private final StringProperty lastName;
private final StringProperty 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 StringProperty firstNameProperty() { return firstName; }
public String getLastName() { return lastName.get(); }
public void setLastName(String lName) { lastName.set(lName); }
public StringProperty lastNameProperty() { return lastName; }
public String getEmail() { return email.get(); }
public void setEmail(String inMail) { email.set(inMail); }
public StringProperty emailProperty() { return email; } // if this method is commented out then the tableview will not refresh when the email is set.
}
}
then i made conclusion myself "eureka! final StringProperty type value can be changed!"
so i had test
package zzzzDelete;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.stage.Stage;
class A{
void someTest(){
B insB = new B("why");
System.out.println(insB.getString());
insB.setString("omg");
System.out.println(insB.getString());
}
class B{
private final StringProperty someString;
private B(String someString){
this.someString = new SimpleStringProperty(someString);
}
public String getString(){
return someString.get();
}
public void setString(String newString){
this.someString = new SimpleStringProperty(newString); // error
}
}
}
public class SomeTest {
public static void main(String[] args){
A a = new A();
a.someTest();
}
}
error is occured because of final keyword.
i'm very confused between first and second example.
When you label a variable as final, it can only be assigned a value once. In your second example, you get a compile error because you try to assign a value to someString in the setString(...) method:
this.someString = new SimpleStringProperty(newString);
This is not allowed, because the setString(...) method can be invoked multiple times on the same object.
By contrast, in your first example, the only time any of the final variables (instance fields) are assigned values is in the constructor, which of course can only be called once for any given object.
Note there is a difference between assigning a value to a reference:
this.someString = new SimpleStringProperty(...);
and changing the state of the object to which the reference points:
this.firstName.set(fName);
The second is perfectly fine even if firstName is final.
If you write class B in the second example to follow the same pattern as the Person class in the first example, it will work fine.
You can't change an immutable (final) field after it has been initialized (which happens in the constructor). Instead, just set the value of the StringProperty via setValue(String):
class B {
private final StringProperty someString;
private B(String someString){
this.someString = new SimpleStringProperty(someString);
}
public String getString(){
return someString.get();
}
public void setString(String newString){
this.someString.setValue(newString);
}
public StringProperty stringProperty() {
return this.someString;
}
}
Read the JavaFX: Properties and Binding Tutorial to see how to use JavaFX properties.
The following picture should clarify how changing the StringProperty works:
Your object of type B always references the same StringProperty object, because the reference someString is final and cannot be changed (see red arrow). But the SimpleStringProperty object that is referenced by someString is mutable. It holds a String reference named value (see green arrow) that can be changed to point to another String object, e.g. by calling the setValue("second") (see green dotted arrow).

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 +
'}';
}
}

Inserting data in a TableView Javafx

I'm trying to insert data into a Javafx TableView, actually I did it, but it fills the row with the following String:
IntegerProperty [value: 72] and etc...
How can I show only the value fill in my rows??
My TableView code:
#FXML TableView tableView = new TableView<MetaDadosInfo>();
#FXML javafx.scene.control.TableColumn instituicaoCol;
#FXML javafx.scene.control.TableColumn anoCol;
#FXML javafx.scene.control.TableColumn tamanhoCol;
#FXML javafx.scene.control.TableColumn tipoCol;
#FXML javafx.scene.control.TableColumn nomeCol;
final ObservableList<MetaDadosInfo> data = FXCollections.observableArrayList(
new MetaDadosInfo(codigoInstituicao, ano, size, type, name));
instituicaoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("codigoInstituicao"));
anoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("ano"));
tamanhoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("size"));
tipoCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("type"));
nomeCol.setCellValueFactory(
new PropertyValueFactory<MetaDadosInfo, String>("name"));
tableView.setItems(data);
MetaDadosInfo class:
public class MetaDadosInfo {
private SimpleIntegerProperty codigoInstituicao;
private SimpleIntegerProperty ano;
private SimpleLongProperty size;
private SimpleStringProperty type;
private SimpleStringProperty name;
public MetaDadosInfo(int codigoInstituicao, int ano, long size, String type, String name) {
this.codigoInstituicao = new SimpleIntegerProperty (codigoInstituicao);
this.ano = new SimpleIntegerProperty (ano);
this.size = new SimpleLongProperty (size);
this.type = new SimpleStringProperty (type);
this.name = new SimpleStringProperty (name);
}
public SimpleIntegerProperty getCodigoInstituicao() {
return codigoInstituicao;
}
public void setCodigoInstituicao(SimpleIntegerProperty codigoInstituicao) {
this.codigoInstituicao = codigoInstituicao;
}
public SimpleIntegerProperty getAno() {
return ano;
}
public void setAno(SimpleIntegerProperty ano) {
this.ano = ano;
}
public SimpleLongProperty getSize() {
return size;
}
public void setSize(SimpleLongProperty size) {
this.size = size;
}
public SimpleStringProperty getType() {
return type;
}
public void setType(SimpleStringProperty type) {
this.type = type;
}
public SimpleStringProperty getName() {
return name;
}
public void setName(SimpleStringProperty name) {
this.name = name;
}
}
The error was in getters and setters from my MetaDadosInfo class, the right way is:
public class MetaDadosInfo {
private SimpleIntegerProperty codigoInstituicao;
private SimpleIntegerProperty ano;
private SimpleLongProperty size;
private SimpleStringProperty type;
private SimpleStringProperty name;
public MetaDadosInfo(int codigoInstituicao, int ano, long size, String type, String name) {
this.codigoInstituicao = new SimpleIntegerProperty (codigoInstituicao);
this.ano = new SimpleIntegerProperty (ano);
this.size = new SimpleLongProperty (size);
this.type = new SimpleStringProperty (type);
this.name = new SimpleStringProperty (name);
}
public int getCodigoInstituicao() {
return codigoInstituicao.get();
}
public void setCodigoInstituicao(int codigoInstituicao) {
this.codigoInstituicao.set(codigoInstituicao);
}
public int getAno() {
return ano.get();
}
public void setAno(int ano) {
this.ano.set(ano);
}
public Long getSize() {
return size.get();
}
public void setSize(long size) {
this.size.set(size);
}
public String getType() {
return type.get();
}
public void setType(String type) {
this.type.set(type);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
}
After wasting my day i finally able to find the solution in very easy way
package test;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class Test extends Application {
public static final String Column1MapKey = "A";
public static final String Column2MapKey = "B";
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(300);
stage.setHeight(500);
final Label label = new Label("Student IDs");
label.setFont(new Font("Arial", 20));
TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A");
TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B");
firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
firstDataColumn.setMinWidth(130);
secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
secondDataColumn.setMinWidth(130);
TableView table_view = new TableView<>();
table_view.setItems(generateDataInMap());
table_view.setEditable(true);
table_view.getSelectionModel().setCellSelectionEnabled(true);
table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
// Callback<TableColumn<Map, String>, TableCell<Map, String>> cellFactoryForMap = new Callback<TableColumn<Map, String>, TableCell<Map, String>>() {
// #Override
// public TableCell call(TableColumn p) {
// return new TextFieldTableCell(new StringConverter() {
// #Override
// public String toString(Object t) {
// return t.toString();
// }
//
// #Override
// public Object fromString(String string) {
// return string;
// }
// });
// }
// };
// firstDataColumn.setCellFactory(cellFactoryForMap);
// secondDataColumn.setCellFactory(cellFactoryForMap);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table_view);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
private ObservableList<Map> generateDataInMap() {
int max = 10;
ObservableList<Map> allData = FXCollections.observableArrayList();
for (int i = 1; i < max; i++) {
Map<String, String> dataRow = new HashMap<>();
String value1 = "A" + i;
String value2 = "B" + i;
dataRow.put(Column1MapKey, value1);
dataRow.put(Column2MapKey, value2);
allData.add(dataRow);
}
return allData;
}
}
just try to change and use it in your way it can also be used directly in resultset
Happy Coding, Happy Innovation
This doesn't work with PropertyValueFactory because you have not declared your JavaFX beans with the expected naming conventions for the properties you have defined in your data model.
Refer to this post for how to use PropertyValueFactory correctly: How to use the PropertyValueFactory correctly?

Categories