Reputation: 1910
Information related to the problem:
I have a class (Shell) that holds a Map of tasks, declared as:
private Map<String, Task> _tabs = new HashMap<String,Task>();
private List<Task> _tsks; //this is the result of the function below:
public List<Task> MapToArray() {
this._tsks = new ArrayList<Task>();
for(String key : _tabs.keySet()) {
this._tsks.add(_tabs.get(key));
}
return this._tsks;
}
My application allows the user to create, edit or delete a Task.
Creation:
shl.createTab(taskName.getText(), taskDescription.getText(), taskAssignee.getText()); //shl is the *Shell* class.
Edition:
public void editTask(String name, String description, String assignee) {
this.deleteTask(loadTask(name));
_currentTab.setAssignee(findUser(assignee));
_currentTab.setDescription(description);
_currentTab.setName(name);
this.setEmployees(this.getEmployees());
this.setManagers(this.getManagers());
this.setTabs(this.getTabs());
this.setUsers(this.getUsers());
}
Deletion:
public void deleteTask(Task currentTab) {
String exName = this.getCurrentTab().getName();
this._tabs.remove(loadTask(exName));
this._tabs.entrySet().remove(exName);
this._tsks.remove(loadTask(exName));
System.out.println("Task '"+ exName + "' deleted");
}
Above, I use the loadTask(name) method, which does the following:
public Task loadTask(String tabName) {
return this._tabs.get(tabName);
}
Finally, my ListView javafx object is declared as:
private ListView<Task> lstView;
And the method that populates it is:
public void refreshList() {
lstView.setItems(FXCollections.observableArrayList(shl.MapToArray())); //once again, shl is the *Shell* class
lstView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
lstView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
System.out.println("clicked on " + lstView.getSelectionModel().getSelectedItem());
shl.setCurrentTab((Task) lstView.getSelectionModel().getSelectedItem());
taskName.setText(shl.getCurrentTab().getName());
description.setText(shl.getCurrentTaskDescription());
name.setText(shl.getCurrentTab().getAssignee());
comment.setText(shl.getCurrentTab().getComment());
}
});
}
Problem itself:
When I create a Task, my ListView is automatically updated and it is added to the list. - great
However, and I just can't understand why, when I edit a task I see that it has successfully changed but my ListView object doesn't refresh/update the list. As soon as I restart my program, my ListView appears updated. - Why is this happening?
Plus, I can't delete any task. When I call the deleteTask method, System prints "Task deleted" but I can still select it on listView and edit it and it is saved with the object so that when I load it the "deleted" task remains.
Upvotes: 0
Views: 1480
Reputation: 98
I didn't completely understand your problem but try this and see if it helps:
Add this where you create "lstview":
lstview.setCellFactory(new Callback<ListView<Task>, ListCell<Task>>() {
@Override
public ListCell<Task> call(ListView<Task> param) {
return new ListCell<Task>(){
@Override
protected void updateItem(Task item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
setText(item.toString());
} else {
setText(null);
}
}
};
}
});
I haven't run this code and it might have errors but the idea is that when you have a listview with an object other than String; you should set cell factory so that the listview knows how to show that object and what to show when the item is empty or null.
Upvotes: 0
Reputation: 224
Use ObservableList instead of List
From the JavaFX Doc
A simple example of how to create and populate a ListView of names (Strings) is shown here:
ObservableList names = FXCollections.observableArrayList( "Julia", "Ian", "Sue", "Matthew", "Hannah", "Stephan", "Denise"); ListView listView = new ListView(names); The elements of the ListView are contained within the items ObservableList. This ObservableList is automatically observed by the ListView, such that any changes that occur inside the ObservableList will be automatically shown in the ListView itself. If passying the ObservableList in to the ListView constructor is not feasible, the recommended approach for setting the items is to simply call:
ObservableList content = ... listView.setItems(content); The end result of this is, as noted above, that the ListView will automatically refresh the view to represent the items in the list. Another approach, whilst accepted by the ListView, is not the recommended approach:
List content = ... getItems().setAll(content); The issue with the approach shown above is that the content list is being copied into the items list - meaning that subsequent changes to the content list are not observed, and will not be reflected visually within the ListView.
Upvotes: 1