加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – ListView没有反映更改

发布时间:2020-12-15 04:20:23 所属栏目:Java 来源:网络整理
导读:我在前面创建了一个TableView,并为每个TableColumns注册了Properties.编辑内部数据反映在TableView中就好了. 但是,使用ListView,它是一个不同的故事.除非我关闭框架并再次打开,否则不会立即显示更改. 我的ListView包含ActionSteps.请注意,我使用了Javafx bea
我在前面创建了一个TableView,并为每个TableColumns注册了Properties.编辑内部数据反映在TableView中就好了.

但是,使用ListView,它是一个不同的故事.除非我关闭框架并再次打开,否则不会立即显示更改.

我的ListView包含ActionSteps.请注意,我使用了Javafx bean属性.

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();
   }

}

我的ListView也使用ObservableList.

@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();

为什么对ObservableList所做的更改不会反映在ListView中?我注意到ListView调用每个对象的toString()来在ListView中显示它们的值,而不是将它绑定到它们的Properties.

我究竟做错了什么?我应该覆盖一家细胞工厂吗?

解决方法

请注意,您尝试使用ListView中的单元格比使用TableView中的单元格执行更复杂的操作.在TableView中,单元格中显示的对象正在发生变化,因此单元格很容易观察到这一点.在ListView中,您希望单元格注意属于单元格中显示的对象的属性何时更改;这是进一步的步骤,所以你必须做一些额外的编码(虽然不多,你会看到).

您可以创建一个自定义单元工厂来绑定到stepNameProperty(),但它很棘手(您必须确保在updateItem()方法中取消绑定/从旧项中删除侦听器).

但是,更简单的方法是使用带定义提取器的ObservableList.

首先,修复您的方法名称:您发布的代码中存在一些奇怪的不匹配. getX / setX / xProperty方法名称应该都正确匹配.即代替

public void setName(String name) {
      stepName.setValue(name);
   }



   public String getName() {
      return stepName.getValue();
   }



   public StringProperty stepNameProperty() {
      return actionStepID;
   }

你应该有

public final void setName(String name) {
      stepName.setValue(name);
   }



   public final String getName() {
      return stepName.getValue();
   }


   public StringProperty nameProperty() {
      return stepName;
   }

并且类似地用于其他属性访问器方法. (显然,字段的名称可以是你喜欢的任何东西,因为它们是私有的.)Making the get/set methods final is good practice.

然后,create the list with an extractor.提取器是一个函数,它将列表中的每个元素映射到列表将观察到的Observables数组.如果这些值发生变化,它将向列表的观察者发送列表更新.由于ActionStep的toString()方法引用了nameProperty(),因此我假设您希望在nameProperty()更改时更新ListView.所以你想做

listOfSteps = FXCollections.observableArrayList(
    actionStep -> new Observable[] { actionStep.nameProperty() } // the "extractor"
  );
  actionStepsListView.setItems(listOfSteps);

请注意,在早期版本的JavaFX 2.2中,ListView没有正确观察更新事件的列表;在Java 8发布之前不久就修复了这个问题(如果我没记错的话).(因为你标记了JavaFX8这个问题,我假设你使用的是Java 8,所以你应该没问题.)

如果您不使用Java 8,则可以使用以下(等效但更详细)代码:

listOfSteps = FXCollections.observableArrayList(
    new Callback<ActionStep,Observable[]>() {
        @Override
        public Observable[] call(ActionStep actionStep) {
            return new Observable[] { actionStep.nameProperty() } ;
        }
    });
actionStepListView.setItems(listOfSteps);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读