带按钮的JavaFX自定义列表单元格:未调用处理程序

时间:2014-08-28 11:54:03

标签: java event-handling javafx handler handle

我有一个ListView来显示一些信息,我创建了一个自定义的CellFactory:每个单元格都有一个标签,一个图像和一个小按钮。我希望用户能够通过单击该小按钮来删除列表行。

列表显示正确,但与按钮关联的处理程序永远不会被调用...

public class ListViewCell extends ListCell<SessionExercise> {
    @Override
    public void updateItem(SessionExercise exercise, boolean empty) {

    ...

    FXMLLoader listItemLoader = new FXMLLoader();
    listItemLoader.setLocation(getClass().
        getResource("/view/SimpleExerciseListItem.fxml"));

    try {
        listItemLoader.load();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    SimpleExerciseListItemController listItemController
            = (SimpleExerciseListItemController) listItemLoader.getController();

    ...

    this.setGraphic(listItemController.getAnchorPane());
}

在我的SimpleExerciseListItemController类中:

public class SimpleExerciseListItemController implements Initializable {
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        btnRemove.
            setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("You clicked the remove button!");

                ...
            }
        });
    }
}

我还尝试过setOnMouseClicked(new EventHandler())而不是setOnAction(new EventHandler()),但没有任何内容打印到控制台......

1 个答案:

答案 0 :(得分:0)

这是known bug,已在最新版本中修复。

您实施ListCell的方式不是推荐的做法;使用推荐的方法还为bug提供了一种解决方法。

问题在于性能问题。对于给定的ListView,创建的单元格相对较少,但updateItem(...)方法可能会多次调用。 (可以说,在某些情况下,需要更多次,但基本的,有意的设计是updateItem(...)可以非常频繁地调用。)

所以你应该只在构造函数中加载你的fxml文件;操纵它并在updateItem(...)方法中设置图形:

public class ListViewCell extends ListCell<SessionExercise> {

    private final SimpleExerciseListItemController listItemController ;

    public ListViewCell() {
        FXMLLoader listItemLoader = new FXMLLoader();
        listItemLoader.setLocation(getClass().
            getResource("/view/SimpleExerciseListItem.fxml"));

        try {
            listItemLoader.load();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        SimpleExerciseListItemController listItemController
                = (SimpleExerciseListItemController) listItemLoader.getController();

        }
        @Override
        public void updateItem(SessionExercise exercise, boolean empty) {
            // don't omit this!!!
            super.updateItem(exercise, empty);

            if (empty) {
                setGraphic(null);
            } else {
                // update controller and ui as necessary

                this.setGraphic(listItemController.getAnchorPane());
            }
        }
}