javafx 2 CheckBoxTableCell not working in tableview - java

I need some help, even my case is simple.
But i can't understand why the check box in the tableview is not geting the value.
I have get the example from the javafx ensemble
I have a class
public class ReservationObj {
private BooleanProperty tcheck;
private StringProperty tname;
private StringProperty tstatus;
private int tser;
public ReservationObj(boolean tcheck, String lname , String lBStatus, int serialinVector) {
this.tcheck = new SimpleBooleanProperty(tcheck);
this.tname = new SimpleStringProperty(lname);
this.tstatus = new SimpleStringProperty(lBStatus);
this.tser = serialinVector;
this.tcheck.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
System.out.println("The check Box is: " + t1);
}
});
}
public BooleanProperty getTcheck() {return tcheck;}
public String getTname() {return tname.getValue() ;}
public void setTname(String tname) {this.tname.set(tname);}
public String getTstatus() {return tstatus.getValue() ;}
public void setTstatus(String tstatus) {this.tstatus.set(tstatus);}
public int getTser() {return tser;}
public void setTser(int tser) { this.tser = tser;}
}
And also i have the.
public Parent createContent() {
final ObservableList<ReservationObj> ReservationList = FXCollections.observableArrayList(
new ReservationObj(true, "aaaaaaaa", "bbbbbbbbb", 1));
TableColumn RCheckCol = new TableColumn<ReservationObj, Boolean>();
RCheckCol.setCellValueFactory(new PropertyValueFactory("tcheck"));
RCheckCol.setText("aaa");
RCheckCol.setCellFactory(new Callback<TableColumn<ReservationObj, Boolean>, TableCell<ReservationObj, Boolean>>() {
public TableCell<ReservationObj, Boolean> call(TableColumn<ReservationObj, Boolean> p) {
return new CheckBoxTableCell<ReservationObj, Boolean>();
}
});
TableColumn RNameCol = new TableColumn();
RNameCol.setCellValueFactory(new PropertyValueFactory("tname"));
RNameCol.setText("bbbb");
TableColumn RAgeCol = new TableColumn();
RAgeCol.setCellValueFactory(new PropertyValueFactory("tstatus"));
RAgeCol.setText("cccc");
TableView AAView = new TableView();
AAView.setItems(ReservationList);
AAView.setEditable(true);
AAView.getColumns().addAll(RCheckCol,RNameCol,RAgeCol);
return AAView;
}
And when simple .
#Override
public void start(Stage primaryStage) {
primaryStage.setScene(new Scene(createContent()));
primaryStage.show();
}
The columns of the tableview are getting the values except from the first “Checkbox”.
Also the listener in the checkbox is not working.
I really don’t understand what I have done wrong. Because I get the example from the ensemble.
Thanks for every idea and any solution.
Elias

Your ReservationObj class doesn’t respect JavaFX Properties convention in naming methods.
If you want to bind the RCheckCol with the tcheck BooleanProperty in :
RCheckCol.setCellValueFactory(new PropertyValueFactory("tcheck"));
You have to provide a tcheckProperty method in your model class:
public BooleanProperty tcheckProperty() {
return tcheck;
}
As an example of a valid JavaFX Bean:
public class Person {
private StringProperty name = new SimpleStringProperty("");
public Person(String name) {
this.name.setValue(name);
}
public String getName() {
return name.getValue();
}
public void setName(String name) {
this.name.setValue(name);
}
public StringProperty nameProperty() {
return name;
}
}

Related

How to bind label.textProperty() to tableView.selectedItem() in JavaFX

I have some problem with understanding bindings in JavaFX.
For example I use simple class Person for showing data in TableView.
public class Person {
private StringProperty name=new SimpleStringProperty();
public Person() {
}
public Person(StringProperty name) {
this.name = name;
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
}
I have PersonDataModel class too
public class PersonDataModel {
private ObservableList<Person> personObservableList= FXCollections.observableArrayList();
private SimpleObjectProperty<Person> singlePerson=new SimpleObjectProperty<>(new Person());
public void listInitialize(){
personObservableList.clear();
personObservableList.add(new Person(new SimpleStringProperty("John")));
personObservableList.add(new Person(new SimpleStringProperty("Mike")));
personObservableList.add(new Person(new SimpleStringProperty("Ana")));
}
public ObservableList<Person> getPersonObservableList() {
return personObservableList;
}
public void setPersonObservableList(ObservableList<Person> personObservableList) {
this.personObservableList = personObservableList;
}
public Person getSinglePerson() {
return singlePerson.get();
}
public SimpleObjectProperty<Person> singlePersonProperty() {
return singlePerson;
}
public void setSinglePerson(Person singlePerson) {
this.singlePerson.set(singlePerson);
}
}
And now I want bind label.textProperty() with selected item in tableView.I use controller class.
public class PersonWindowController {
private PersonDataModel personDataModel=new PersonDataModel();
#FXML
private TableView<Person> nameTableView;
#FXML
private TableColumn<Person, String> nameTableColumn;
#FXML
private Label nameLabel;
#FXML
public void initialize(){
personDataModel.listInitialize();
nameTableColumn.setCellValueFactory(cellData->cellData.getValue().nameProperty());
nameTableView.setItems(personDataModel.getPersonObservableList());
nameLabel.textProperty().bind(personDataModel.getSinglePerson().nameProperty());
nameTableView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
if(newValue!=null) {
//1. Option doesn't work
//personDataModel.setSinglePerson(newValue);
//System.out.println(personDataModel.getSinglePerson().getName());
//2. Option works
personDataModel.getSinglePerson().setName(newValue.getName());
System.out.println(personDataModel.getSinglePerson().getName());
}
});
}
}
My questions are:
Why first option doesn't work ?. I changed singlePerson object but nameLabel didn't change.
I don't want to set all properties one by one when Person class will be more complicated. How to avoid this ?.
When singlePerson in PersonDataModel is just an object of Person class not SimpleObjectProperty the programm behaves exactly the same. Is any advantage to use SimpleObjectProperty in my example ?
Sorry for all mistakes I've made. Thanks in advance for your help.
Greg
Edit1: I edited my question after user Kleopatra answer.

JavaFX - TableView - setItems : The method setItems(ObservableList) in the type TableView is not applicable for the arguments (ObservableList)

I've a problem when I try to set my items into a tableView, for information I use SceneBuilder.
Main.java :
public class Main extends Application {
private static Stage theStage;
public static void main(String[] args) throws Exception {
testDatas();
launch();
}
public void start(Stage stage) throws IOException {
theStage = stage;
Group acteur = new Group();
acteur.getChildren().add(
FXMLLoader.load(getClass().getResource("views/options.fxml")));
theStage.setTitle("Where's My Money");
Scene scene = new Scene(acteur, 1280.0, 720.0);
theStage.setScene(scene);
theStage.show();
}
public static void initialize() {
launch();
}
public static void setScene(Group acteur, String titre) throws IOException {
Scene scene = new Scene(acteur);
theStage.setTitle(titre);
theStage.setScene(scene);
theStage.show();
}
}
views/ControllerOptions.class
public class ControllerOptions implements Initializable{
#FXML private TableView<?> TV_currency;
#FXML private TableColumn<Currency, String> TC_name;
#FXML private TableColumn<Currency, Double> TC_value;
private ObservableList<Currency> currencies = FXCollections.observableArrayList();
//FUNCTIONS
#Override
public void initialize(URL location, ResourceBundle rb){
//initialisation Table Currencies
for (Currency currency : Datas.getInstance().getCurrencies()) {
currencies.add(currency);
}
TC_name.setCellValueFactory(new PropertyValueFactory<Currency, String>("name"));
TC_value.setCellValueFactory(new PropertyValueFactory<Currency, Double>("value"));
TV_currency.setItems(currencies); // <= HERE'S THE ERROR
}
}
Models/Currency.class
public class Currency {
private String name;
private double value;
public Currency(String name, double value) {
setName(name);
setValue(value);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setValue(double value) {
this.value = value;
}
public double getValue() {
return value;
}
}
I've this error :
The method setItems(ObservableList) in the type TableView is not applicable for the arguments (ObservableList)
If you can help me I'll be very gratefull.
Thanks in advance
You declared the backing data correctly as
private ObservableList<Currency> currencies ;
but you declared the table using a wildcard:
#FXML private TableView<?> TV_currency;
Consequently, the types don't match when you try to set the items in the table.
Change the declaration of the table to
#FXML private TableView<Currency> TV_currency;

JavaFX date formatting within a TableView using legacy beans

I have a TableView that is sourced from an attribute in a legacy Java Bean of type java.util.Date. I wish to customize the formatting of the date String to HH:mm:ss
I'm looking for is a native JavaFX utility to create an ObservableValue wrapper taking a java.util.DateFormat or javafx.util.StringConverter
I've found Bindings.format() class which could be used to wrap the ObservableValue, however this only allows printf format patterns like %04d etc, not any custom date specific formatting.
The best I've come up with is to use Bindings.bindBidirectional(property, property, format) with a dummy StringProperty which the CellFactory returns. Can this be simplified? Could this cause a memory leak?
public class OldBeanTableView extends Application {
public class OldBean {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public static final String PROPERTY_NAME_FOO = "foo";
private Date foo = new Date();
public Date getFoo() {
return foo;
}
public void setFoo(Date foo) {
Date oldValue = this.foo;
this.foo = foo;
pcs.firePropertyChange(PROPERTY_NAME_FOO, oldValue, foo);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
private class LegacyValueFactory<T, F> implements Callback<CellDataFeatures<T, String>, ObservableValue<String>> {
private String propertyName;
private Format format;
public LegacyValueFactory(String propertyName, Format format) {
this.propertyName = propertyName;
this.format = format;
}
#Override
public ObservableValue<String> call(CellDataFeatures<T, String> param) {
try {
Property<String> formattedString = new SimpleStringProperty();
Property<F> original = JavaBeanObjectPropertyBuilder.create().name(propertyName).bean(param.getValue()).build();
Bindings.bindBidirectional(formattedString, original, format);
return formattedString;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
#Override
public void start(Stage primaryStage) throws Exception {
ObservableList<OldBean> beans = FXCollections.observableArrayList();
beans.add(new OldBean());
TableView<OldBean> tableView = new TableView<>();
TableColumn<OldBean, String> column = new TableColumn<OldBeanTableView.OldBean, String>();
tableView.getColumns().add(column);
column.setCellValueFactory(new LegacyValueFactory<OldBean, String>("foo", new SimpleDateFormat("HH:mm:ss")));
tableView.setItems(beans);
primaryStage.setScene(new Scene(tableView));
primaryStage.show();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
() -> beans.get(0).setFoo(new Date(beans.get(0).getFoo().getTime() + 1000)), 0, 1, TimeUnit.SECONDS);
}
public static void main(String[] args) {
launch(args);
}
}
Based on James_D suggestion this can be done using a CellFactory instead of a CellValueFactory...
public class FormattedTableCell<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private Format format;
public FormattedTableCell(Format format) {
super();
this.format = format;
}
#Override
public TableCell<S, T> call(TableColumn<S, T> param) {
return new TableCell<S, T>() {
#Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(format.format(item));
}
}
};
}
}
Usage
column.setCellFactory(new FormattedTableCell<OldBean, Date>(new SimpleDateFormat("HH:mm:ss")));

JavaFx: can data binding (textfield) be used in production mode?

I use java 8.0.45. I have implemented my first javafx application (very simple) with data binding. However, biding from user input-> pojo seems to work with bugs. I've checked about 200 times. I entered new values in text fields and after that I checked model values. The same code, the same my behaviour. Sometimes everything works fine (in most cases - about 80-90%) sometimes model value!=textfield value. I've noticed the following. Data binding for some certain text field works,works and then at some point of time that binding stops working and all new values for this certain textfield are not passed to model. Nor exceptions. Nor any warnings. Nothing. Just binding doesn't work.
I have 4 textfiled which are created via fxml. Two for string model type. One for integer. One for bigdecimal. The problem happens to all these fields(sometimes to one, sometimes to several). As my number fields can have null values, I use for example PropertyObject but not IntegerProperty (people from openjfx advised so).
So is this JavaFx bug or what? P.S. I use felix osgi, weld cdi, and pax - I don't know if it matters...
My code is the following:
DTO - POJO Model
public class Task {
private String name;
private Integer order;
private BigDecimal weight;
private String comment;
private final PropertyChangeSupport propertyChangeSupport;
public Task() {
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
public String getName() {
return name;
}
public void setName(String name) {
String pv = this.name ;
this.name = name;
propertyChangeSupport.firePropertyChange("name", pv, name);
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
Integer pv = this.order;
this.order = order;
propertyChangeSupport.firePropertyChange("order", pv, this.order);
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
BigDecimal pv = this.weight;
this.weight = weight;
propertyChangeSupport.firePropertyChange("weight", pv, weight);
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
String pv = this.comment;
this.comment = comment;
propertyChangeSupport.firePropertyChange("comment", pv, this.comment);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
}
Adapter
public class TaskAdapter {
private StringProperty nameProperty;
private ObjectProperty<Integer> orderProperty;
private ObjectProperty<BigDecimal> weightProperty;
private StringProperty commentProperty;
public TaskAdapter(Task task) {
try {
nameProperty=new JavaBeanStringPropertyBuilder().bean(task).name("name").build();
orderProperty=new JavaBeanObjectPropertyBuilder<Integer>().bean(task).name("order").build();
weightProperty=new JavaBeanObjectPropertyBuilder<BigDecimal>().bean(task).name("weight").build();
commentProperty=new JavaBeanStringPropertyBuilder().bean(task).name("comment").build();
} catch (NoSuchMethodException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
}
public StringProperty getNameProperty() {
return nameProperty;
}
public ObjectProperty<Integer> getOrderProperty() {
return orderProperty;
}
public ObjectProperty<BigDecimal> getWeightProperty() {
return weightProperty;
}
public StringProperty getCommentProperty() {
return commentProperty;
}
}
BigDecimal Converter
public class SimpleBigDecimalStringConverter extends StringConverter<BigDecimal>{
#Override
public String toString(BigDecimal i) {
if (i == null) {
return "" ;
} else {
return i.toString();
}
}
#Override
public BigDecimal fromString(String string) {
if (string.trim().length() == 0) {
return null ;
} else {
try {
return new BigDecimal(string);
} catch (NumberFormatException nfe) {
return null ;
}
}
}
}
IntegerConverter
public class SimpleIntegerStringConverter extends StringConverter<Integer>{
#Override
public String toString(Integer i) {
if (i == null) {
return "" ;
} else {
return i.toString();
}
}
#Override
public Integer fromString(String string) {
if (string.trim().length() == 0) {
return null ;
} else {
try {
return Integer.valueOf(string);
} catch (NumberFormatException nfe) {
return null ;
}
}
}
}
Initializing code
Task task=new Task();
TaskAdapter adapter=new TaskAdapter(task);
nameTextField.textProperty().bindBidirectional(adapter.getNameProperty());
orderTextField.textProperty().bindBidirectional(adapter.getOrderProperty(),new SimpleIntegerStringConverter());
weightTextField.textProperty().bindBidirectional(adapter.getWeightProperty(),new BigDecimalStringConverter());
commentTextField.textProperty().bindBidirectional(adapter.getCommentProperty());
What is happening
JavaFX Bindings use WeakChangeListeners behind the scenes to implement the binding. This means that the binding itself can be garbage collected if no other references to it are in scope. In your code, the adapter is defined as a local variable, so it gets prematurely garbage collected at some arbitrary time when the gc runs.
Demo
Here's a demo using your code that shows the issue. It has the same text fields you define, plus two buttons. One button dumps the value of the task to the console, the other forces the garbage collector to run. You'll see that the binding stops working as soon as you run the gc.
import javafx.application.Application;
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.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.converter.BigDecimalStringConverter;
public class POJOBindingExample extends Application {
private TextField nameTextField = new TextField();
private TextField orderTextField = new TextField();
private TextField weightTextField = new TextField();
private TextField commentTextField = new TextField();
#Override
public void start(Stage primaryStage) {
Task task = new Task();
TaskAdapter adapter = new TaskAdapter(task);
nameTextField.textProperty().bindBidirectional(adapter.getNameProperty());
orderTextField.textProperty().bindBidirectional(adapter.getOrderProperty(),new SimpleIntegerStringConverter());
weightTextField.textProperty().bindBidirectional(adapter.getWeightProperty(),new BigDecimalStringConverter());
commentTextField.textProperty().bindBidirectional(adapter.getCommentProperty());
GridPane grid = new GridPane();
grid.addRow(0, new Label("Name:"), nameTextField);
grid.addRow(1, new Label("Order:"), orderTextField);
grid.addRow(2, new Label("Weight:"), weightTextField);
grid.addRow(3, new Label("Comment:"), commentTextField);
Button showButton = new Button("Show Task");
showButton.setOnAction(e -> {
System.out.println(task.getName());
System.out.println(task.getOrder());
System.out.println(task.getWeight());
System.out.println(task.getComment());
System.out.println();
});
Button gcButton = new Button("Run GC");
gcButton.setOnAction(e -> System.gc());
HBox buttons = new HBox(10, showButton, gcButton);
BorderPane.setAlignment(grid, Pos.CENTER);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(grid, new Insets(10));
BorderPane.setMargin(buttons, new Insets(10));
BorderPane root = new BorderPane(grid, null, null, buttons, null);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Fix
To fix the problem, you need to ensure a reference to the TaskAdapter persists as long as you need it. In the above code, if you move the reference to the TaskAdapter so that it is an instance field, everything will work as required:
public class POJOBindingExample extends Application {
private TextField nameTextField = new TextField();
private TextField orderTextField = new TextField();
private TextField weightTextField = new TextField();
private TextField commentTextField = new TextField();
private TaskAdapter adapter;
#Override
public void start(Stage primaryStage) {
Task task = new Task();
adapter = new TaskAdapter(task);
// ... etc
}
}
You might also be interested in reading Tomas Mikula's blog, though I don't think you can use his library directly to implement binding to a POJO.

ListView is not reflecting changes

I created a TableView a while back and registered Properties to each of the TableColumns. Editing of the internal data reflected itself back in the TableView just fine.
With a ListView, however, it is a different story. The changes are not being shown right away unless I close the frame and open it again.
My ListView consists of ActionSteps. Note that I used the Javafx beans properties.
package application.objects;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.function.IntPredicate;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class ActionStep {
private StringProperty actionStepID;
private ObjectProperty<LocalDate> dateSet, dateFinished;
private StringProperty stepName;
private IntegerProperty completion;
private ArrayList<StepComment> comments;
public ActionStep(String name) {
actionStepID = new SimpleStringProperty();
stepName = new SimpleStringProperty();
dateSet = new SimpleObjectProperty<LocalDate>();
dateFinished = new SimpleObjectProperty<LocalDate>();
completion = new SimpleIntegerProperty();
stepName.setValue(name);
}
public void setName(String name) {
stepName.setValue(name);
}
public String getName() {
return stepName.getValue();
}
public StringProperty stepNameProperty() {
return actionStepID;
}
public void setID(String id) {
actionStepID.setValue(id);
}
public String getID() {
return actionStepID.get();
}
public StringProperty actionStepIDProperty() {
return actionStepID;
}
public void setCompletion(int percent) {
if (percent < 0 || percent > 100)
return;
completion.set(percent);
}
public int getCompletion() {
return completion.get();
}
public IntegerProperty completionProperty() {
return completion;
}
public void setDateSet(LocalDate date) {
dateSet.set(date);
}
public LocalDate getDateSet() {
return dateSet.get();
}
public ObjectProperty<LocalDate> dateSetProperty() {
return dateSet;
}
public void setDateFinished(LocalDate date) {
dateFinished.set(date);
}
public LocalDate getDateFinished() {
return dateFinished.get();
}
public ObjectProperty<LocalDate> dateFinishedProperty() {
return dateFinished;
}
public String toString() {
return stepNameProperty().get();
}
}
My ListView uses an ObservableList as well.
#FXML
private ListView<ActionStep> actionStepsListView;
private ObservableList<ActionStep> listOfSteps;
listOfSteps = FXCollections.observableArrayList();
actionStepsListView.setItems(listOfSteps);
if (plan != null) {
ArrayList<ActionStep> arrayOfSteps = plan.getStepsArrayList();
for (int i = 0; i < arrayOfSteps.size(); i++)
listOfSteps.add(arrayOfSteps.get(i));
} else
plan = new ActionPlan();
How come changes made to the ObservableList do not reflect themselves in the ListView? I noticed that the ListView called upon every object's toString() to display their values in the ListView, rather than binding it to their Properties.
What am I doing wrong? Am I supposed to override a cell factory or something?
Note that you're trying to do something more complex with the cells in your ListView than you were with the cells in the TableView. In the TableView, the objects displayed in the cells were changing, so it was easy for the cells to observe this. In the ListView, you want the cells to notice when properties that belong to the objects displayed in the cells change; this is one further step removed, so you have to do a bit of extra coding (though not much, as you'll see).
You could create a custom cell factory to bind to the stepNameProperty(), but it's tricky (you have to make sure to unbind/remove listeners from old items in the updateItem() method).
The easier way, though, which isn't well documented is to use an ObservableList with an extractor defined.
First, fix your method names: you have some weird mismatches in the code you posted. The getX/setX/xProperty method names should all match correctly. I.e. instead of
public void setName(String name) {
stepName.setValue(name);
}
public String getName() {
return stepName.getValue();
}
public StringProperty stepNameProperty() {
return actionStepID;
}
you should have
public final void setName(String name) {
stepName.setValue(name);
}
public final String getName() {
return stepName.getValue();
}
public StringProperty nameProperty() {
return stepName;
}
and similarly for the other property accessor methods. (Obviously, the names of the fields can be anything you like, as they're private.) Making the get/set methods final is good practice.
Then, create the list with an extractor. The extractor is a function that maps each element in the list to an array of Observables which the list will observe. If those values change, it will fire list updates to the list's observers. Since your ActionStep's toString() method references the nameProperty(), I assume you want the ListView to update if the nameProperty() changes. So you want to do
listOfSteps = FXCollections.observableArrayList(
actionStep -> new Observable[] { actionStep.nameProperty() } // the "extractor"
);
actionStepsListView.setItems(listOfSteps);
Note that in earlier versions of JavaFX 2.2 the ListView did not properly observe the list for update events; this was fixed (if I remember correctly) shortly prior to the release of Java 8. (Since you tagged the question JavaFX8, I assume you're using Java 8 and so you should be fine here.)
If you are not using Java 8, you can use the following (equivalent but more verbose) code:
listOfSteps = FXCollections.observableArrayList(
new Callback<ActionStep, Observable[]>() {
#Override
public Observable[] call(ActionStep actionStep) {
return new Observable[] { actionStep.nameProperty() } ;
}
});
actionStepListView.setItems(listOfSteps);
Here is sample how make listview with custom objects:
public class JavaFX_ListView extends Application {
class MyObject {
String day;
int number;
MyObject(String d, int n) {
day = d;
number = n;
}
String getDay() {
return day;
}
int getNumber() {
return number;
}
#Override
public String toString() {
return number + " " + day;
}
}
ObservableList<MyObject> myList;
// Create dummy list of MyObject
private void prepareMyList() {
myList = FXCollections.observableArrayList();
myList.add(new MyObject("Sunday", 50));
myList.add(new MyObject("Monday", 60));
myList.add(new MyObject("Tuesday", 20));
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("sample");
prepareMyList();
ListView<MyObject> listView = new ListView<>();
listView.setItems(myList);
Pane root = new Pane();
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
// testing
Timer timer = new Timer();
timer.schedule(new UpdateListTask(), 1000, 1000);
}
public static void main(String[] args) {
launch(args);
}
// testing
public class UpdateListTask extends TimerTask {
#Override
public void run() {
Platform.runLater(new Runnable() {
#Override
public void run() {
myList.add(new MyObject("sample", Calendar.getInstance()
.getTime().getSeconds()));
}
});
}
}
}

Categories

Resources