为JavaFX定义自定义Comparator TableView列呈现为SimpleObjectProperty <imageview>

时间:2017-08-20 14:30:22

标签: java javafx

我有一个具有不同列的表,我要添加自定义组件的那个的签名是这样的:

@FXML
private TableColumn<Media,SimpleObjectProperty<ImageView>> hasBeenPlayed;

因此该列呈现为ImageView。它有两种可能的状态,Imageview将有null图像,或ImageView将有一个图像,我已定义的特定图像。

所以我想要的是排序基于我 f ImageView有空图像,如果ImageView有图像,所以我做了下面的Comparator但是它报告错误我不知道为什么......

hasBeenPlayed.setComparator( new Comparator<SimpleObjectProperty<ImageView>>() {
   @Override
   public int compare(SimpleObjectProperty<ImageView> o1 , SimpleObjectProperty<ImageView> o2) {
      if (o1.get().getImage() == o2.get().getImage())
         return 0;
      return -1;
   }
});

我应该使用上面的lambda表达式,我以这种方式添加它以更加明显我想要实现的目标。

我得到的错误是......

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException:
  javafx.scene.image.ImageView cannot be cast to javafx.beans.property.SimpleObjectProperty

正如James_D对评论所要求的那样:

Cell Value Factory:

hasBeenPlayed.setCellValueFactory(new PropertyValueFactory<>("hasBeenPlayed"));

模型的一部分Media

public abstract class Media {

 .....

 /** The has been played. */
 private SimpleObjectProperty<ImageView> hasBeenPlayed;

 .....

 /**
 * Checks for been played property.
 *
 * @return the simple object property
 */
 public SimpleObjectProperty<ImageView> hasBeenPlayedProperty() {
    return hasBeenPlayed;
 }

}

1 个答案:

答案 0 :(得分:2)

您的代码存在多个问题。

首先,您将UI元素放在item类中,这是您应该避免的。列的名称提示显示的属性只有2个状态。布尔属性更合适。

使用自定义cellFactory显示图片。

此外,根据错误消息,列的实际类型应为TableColumn<Media, ImageView>

此外,您违反了Comparator的合同,使其成为非对称的。

您必须确保满足以下条件:

如果comparator.compare(a, b) < 0comparator.compare(b, a) > 0。在您的情况下,除非所有ImageView包含相同的图像(或全部包含null),否则不会达到此目的。

除了使属性成为布尔属性外,还修改这样的代码:

@FXML
private TableColumn<Media, Boolean> hasBeenPlayed;
hasBeenPlayed.setComparator((v1, v2) -> Boolean.compare(v1, v2));

或者

hasBeenPlayed.setComparator((v1, v2) -> -Boolean.compare(v1, v2));

并将以下内容添加到控制器的initialize方法

final Image playedImage = new Image(...);

hasBeenPlayed.setCellFactory(col -> new TableCell<Media, Boolean>() {
    private final ImageView image = new ImageView();

    {
        setGraphic(image);
        image.setFitWidth(playedImage.getWidth());
        image.setFitHeight(playedImage.getHeight());
    }

    @Override
    protected void updateItem(Boolean item, boolean empty) {
         super.updateItem(item, empty);

         // set the image according to the played state
         image.setImage(item != null && item ? playedImage : null);
    }
});