将 ContextMenu 添加到 ListView<File> 会导致空行显示 null

Adding a ContextMenu to a ListView<File> results in empty rows showing null

我正在使用 CellFactory 将 ContextMenu 添加到 ListView,如图 所示。我使用 ListView<File> 而不是 ListView<String>。问题是 ListView 中的空行显示 "null"。这是由

行引起的

cell.textProperty().bind(cell.itemProperty().asString());

但我不能忽略它,否则即使行不为空,所有行都是空白的。

绑定 cell.textProperty() 以在行为空时不显示 null 的正确方法是什么?

public class FileUploaderVBox extends VBox {

    ListView<File> filesToUpload = new ListView<>();

    public FileUploaderVBox(Stage primaryStage) {
        setAlignment(Pos.TOP_CENTER);

        Label l = new Label("Select Files to Upload");
        l.setStyle("-fx-font: 12 arial; -fx-font-weight: bold;");
        setMargin(l, new Insets(25,0,20,0));

        Separator horizSeparator1 = new Separator();
        horizSeparator1.prefWidthProperty().bind(widthProperty());


        filesToUpload.setCellFactory(lv -> {

            ListCell<File> cell = new ListCell<>();

            ContextMenu contextMenu = new ContextMenu();


            MenuItem deleteItem = new MenuItem();
            deleteItem.textProperty().bind(Bindings.format("Delete \"%s\"", cell.itemProperty()));
            deleteItem.setOnAction(event -> filesToUpload.getItems().remove(cell.getItem()));

            contextMenu.getItems().addAll(deleteItem);

//            cell.textProperty().bind(cell.itemProperty());
            cell.textProperty().bind(cell.itemProperty().asString());

        cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
            if (isNowEmpty) {
                cell.setContextMenu(null);
            } else {
                cell.setContextMenu(contextMenu);
            }
        });

            return cell ;
        });

        Separator horizSeparator2 = new Separator();
        horizSeparator2.prefWidthProperty().bind(widthProperty());

        Button chooseFileButton = new Button("Choose File");

        chooseFileButton.setOnAction(new EventHandler<ActionEvent> () {

            @Override
            public void handle(ActionEvent event) {

                FileChooser fileChooser = new FileChooser();
                File f = fileChooser.showOpenDialog(primaryStage);
                if (null != f)
                    filesToUpload.getItems().add(f);
            }
        });

        getChildren().addAll(l, horizSeparator1, filesToUpload, horizSeparator2, chooseFileButton);

    }

    public ObservableList<File> getFilesToUpload() {
        return filesToUpload.getItems();
    }
}

编辑

cell.textProperty().bind(cell.itemProperty().asString()) 替换为以下内容会产生 WhosebugError。

    ObjectProperty<File> itemProperty = cell.itemProperty();
    StringBinding sb = Bindings.createStringBinding(new Callable<String>() {

        @Override
        public String call() throws Exception {

            if (null == itemProperty)
                return "";
            else
                return itemProperty.toString();
        }

    }, itemProperty);

    cell.textProperty().bind(sb);

什么鬼?

您可以尝试这样的操作:

StringBinding stringBinding = new StringBinding(){
      {
       super.bind(cell.itemProperty().asString());
      }
      @Override
      protected String computeValue() {
          if(cell.itemProperty().getValue()==null){
              return "";
          }
          return cell.itemProperty().getValue().getPath();
     }
};

cell.textProperty().bind(stringBinding);