ListView is not reflecting changes

前端 未结 2 1124
一整个雨季
一整个雨季 2020-12-06 09:04

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.

相关标签:
2条回答
  • 2020-12-06 09:17

    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);
    
    0 讨论(0)
  • 2020-12-06 09:25

    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()));
                    }
                });
            }
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题