Java 为什么getTableRow().getItem()返回空引用,即使不是空行?

Java 为什么getTableRow().getItem()返回空引用,即使不是空行?,java,javafx,Java,Javafx,所以我创建了这个带有搜索栏和表视图的小应用程序。当屏幕初始化时,我使用tableView.setItems()将项目的固定列表添加到我的表中。稍后,当用户执行查询时,将生成一个过滤列表,我再次调用tableView.setItems()。呈现列表时,我的代码对getRowTable().getItem()调用方法,以向每行中的按钮添加行为。所有内容都正确呈现,但是,updateItem()似乎被调用的次数超过了它应该被调用的次数,并且getRowTable().getItem()返回一个null

所以我创建了这个带有搜索栏和表视图的小应用程序。当屏幕初始化时,我使用
tableView.setItems()
将项目的固定列表添加到我的表中。稍后,当用户执行查询时,将生成一个过滤列表,我再次调用
tableView.setItems()
。呈现列表时,我的代码对
getRowTable().getItem()
调用方法,以向每行中的按钮添加行为。所有内容都正确呈现,但是,
updateItem()
似乎被调用的次数超过了它应该被调用的次数,并且
getRowTable().getItem()
返回一个
null
引用,使程序抛出异常

这是什么原因造成的?代码如下

App.java

public class SearchMovies {
    @FXML TextField searchField;
    @FXML TableView<Movie> tableView;
    @FXML TableColumn<Movie, String> titleColumn;
    @FXML TableColumn<Movie, String> directorColumn;
    @FXML TableColumn<Movie, Void> likeColumn;

    private ArrayList<Movie> movieList = new ArrayList<>(Arrays.asList(
        new Movie("Persona", "Ingmar Bergman"),
        new Movie("City of God", "Fernando Meirelles"),
        new Movie("Pulp Fiction", "Quentin Tarantino"),
        new Movie("Gone Girl", "David Fincher"),
        new Movie("Fight Club", "David Fincher"),
        new Movie("Perfect Blue", "Satoshi Kon"),
        new Movie("Prisoners", "Denis Villeneuve"),
        new Movie("Sin City", "Frank Miller"),
        new Movie("Mean Girls", "Mark Waters"),
        new Movie("Breakfast Club", "John Hughes"),
        new Movie("Sixteen Candles", "John Hughes"),
        new Movie("Reservoir Dogs", "Quentin Tarantino")
    ));

    private ObservableList<Movie> observableMovieList = FXCollections.observableArrayList(movieList);

    @FXML
    public void initialize() {
        titleColumn.setCellValueFactory(item -> item.getValue().titleProperty());
        directorColumn.setCellValueFactory(item -> item.getValue().directorProperty());

        likeColumn.setCellFactory(col -> new TableCell<Movie, Void>() {
            private final Button button = new Button("LIKE");

            @Override
            public void updateItem(Void item, boolean empty) {
                super.updateItem(item, empty);

                if (empty) {
                    setGraphic(null);
                } else {
                    Movie movie = getTableRow().getItem();
                    button.setOnAction(e -> System.out.println("Someone liked " + movie.getTitle() + " " + movie.getDirector()));
                    System.out.println("Rendering row for " + movie.getTitle() + " by " + movie.getDirector());
                    setGraphic(button);
                }
            }
        });

        tableView.setItems(observableMovieList);
    }

    @FXML
    public void search() {
        String query = searchField.getText();

        if (query == null || query.isBlank() || query.isEmpty()) {
            return;
        }

        observableMovieList = FXCollections.observableArrayList(filterMovies(query));
        tableView.setItems(observableMovieList);
    }

    private ArrayList<Movie> filterMovies(String query) {
        ArrayList<Movie> filteredMovies = new ArrayList<>();

        for (Movie movie : movieList) {
            if (movie.getTitle().contains(query) || movie.getDirector().contains(query)) {
                filteredMovies.add(movie);
            }
        }

        return filteredMovies;
    }

    private class Movie {
        private final StringProperty title;
        private final StringProperty director;

        public Movie(String title, String director) {
            this.title = new SimpleStringProperty(title);
            this.director = new SimpleStringProperty(director);
        }

        public String getTitle() {
            return title.get();
        }

        public StringProperty titleProperty() {
            return title;
        }

        public void setTitle(String title) {
            this.title.set(title);
        }

        public String getDirector() {
            return director.get();
        }

        public StringProperty directorProperty() {
            return director;
        }

        public void setDirector(String director) {
            this.director.set(director);
        }
    }
}
公共类应用程序扩展应用程序{
@凌驾
public void start(Stage primaryStage)引发异常{
URL URL=getClass().getResource(“/com/lib/fxml/search movies.fxml”);
试一试{
父根=FXMLLoader.load(url);
场景=新场景(根,1024768);
初级阶段。场景(场景);
primaryStage.show();
}捕获(IOException异常){
异常。printStackTrace();
}
}
公共静态void main(字符串[]args){
发射(args);
}
}
SearchMovies.java

public class SearchMovies {
    @FXML TextField searchField;
    @FXML TableView<Movie> tableView;
    @FXML TableColumn<Movie, String> titleColumn;
    @FXML TableColumn<Movie, String> directorColumn;
    @FXML TableColumn<Movie, Void> likeColumn;

    private ArrayList<Movie> movieList = new ArrayList<>(Arrays.asList(
        new Movie("Persona", "Ingmar Bergman"),
        new Movie("City of God", "Fernando Meirelles"),
        new Movie("Pulp Fiction", "Quentin Tarantino"),
        new Movie("Gone Girl", "David Fincher"),
        new Movie("Fight Club", "David Fincher"),
        new Movie("Perfect Blue", "Satoshi Kon"),
        new Movie("Prisoners", "Denis Villeneuve"),
        new Movie("Sin City", "Frank Miller"),
        new Movie("Mean Girls", "Mark Waters"),
        new Movie("Breakfast Club", "John Hughes"),
        new Movie("Sixteen Candles", "John Hughes"),
        new Movie("Reservoir Dogs", "Quentin Tarantino")
    ));

    private ObservableList<Movie> observableMovieList = FXCollections.observableArrayList(movieList);

    @FXML
    public void initialize() {
        titleColumn.setCellValueFactory(item -> item.getValue().titleProperty());
        directorColumn.setCellValueFactory(item -> item.getValue().directorProperty());

        likeColumn.setCellFactory(col -> new TableCell<Movie, Void>() {
            private final Button button = new Button("LIKE");

            @Override
            public void updateItem(Void item, boolean empty) {
                super.updateItem(item, empty);

                if (empty) {
                    setGraphic(null);
                } else {
                    Movie movie = getTableRow().getItem();
                    button.setOnAction(e -> System.out.println("Someone liked " + movie.getTitle() + " " + movie.getDirector()));
                    System.out.println("Rendering row for " + movie.getTitle() + " by " + movie.getDirector());
                    setGraphic(button);
                }
            }
        });

        tableView.setItems(observableMovieList);
    }

    @FXML
    public void search() {
        String query = searchField.getText();

        if (query == null || query.isBlank() || query.isEmpty()) {
            return;
        }

        observableMovieList = FXCollections.observableArrayList(filterMovies(query));
        tableView.setItems(observableMovieList);
    }

    private ArrayList<Movie> filterMovies(String query) {
        ArrayList<Movie> filteredMovies = new ArrayList<>();

        for (Movie movie : movieList) {
            if (movie.getTitle().contains(query) || movie.getDirector().contains(query)) {
                filteredMovies.add(movie);
            }
        }

        return filteredMovies;
    }

    private class Movie {
        private final StringProperty title;
        private final StringProperty director;

        public Movie(String title, String director) {
            this.title = new SimpleStringProperty(title);
            this.director = new SimpleStringProperty(director);
        }

        public String getTitle() {
            return title.get();
        }

        public StringProperty titleProperty() {
            return title;
        }

        public void setTitle(String title) {
            this.title.set(title);
        }

        public String getDirector() {
            return director.get();
        }

        public StringProperty directorProperty() {
            return director;
        }

        public void setDirector(String director) {
            this.director.set(director);
        }
    }
}
公共类搜索电影{
@FXML文本字段搜索字段;
@FXML表视图表视图;
@FXML表柱滴定柱;
@FXML表格柱状指示柱;
@FXML TableColumn-likeColumn;
private ArrayList movieList=新的ArrayList(Arrays.asList(
新电影(“人物角色”、“英格玛·伯格曼”),
新电影(“上帝之城”、“费尔南多·梅雷莱斯”),
新电影(“低俗小说”、“昆汀·塔伦蒂诺”),
新电影(“走失的女孩”、“大卫·芬奇”),
新电影(“搏击俱乐部”、“大卫·芬奇”),
新电影(“完美蓝色”,“Satoshi Kon”),
新电影(“囚犯”,“丹尼斯·维伦纽夫”),
新电影(“罪恶之城”、“弗兰克·米勒”),
新电影(“卑鄙女孩”、“马克·沃特斯”),
新电影(“早餐俱乐部”、“约翰·休斯”),
新电影(“十六支蜡烛”,“约翰休斯”),
新电影(“水库狗”,“昆汀塔伦蒂诺”)
));
私有ObservableList observableMovieList=FXCollections.observableArrayList(movieList);
@FXML
公共无效初始化(){
titleColumn.setCellValueFactory(item->item.getValue().titleProperty());
directorColumn.setCellValueFactory(item->item.getValue().directorProperty());
比如column.setCellFactory(col->newTableCell(){
私有最终按钮=新按钮(“类似”);
@凌驾
公共无效更新项(无效项,布尔值为空){
super.updateItem(项,空);
if(空){
设置图形(空);
}否则{
Movie Movie=getTableRow().getItem();
setOnAction(e->System.out.println(“某人喜欢”+movie.getTitle()+“+movie.getDirector());
System.out.println(“通过“+movie.getDirector()”)为“+movie.getTitle()+”呈现行);
设置图形(按钮);
}
}
});
tableView.setItems(observableMovieList);
}
@FXML
公开无效搜索(){
String query=searchField.getText();
if(query==null | | query.isBlank()| | query.isEmpty()){
返回;
}
observableMovieList=FXCollections.observableArrayList(filterMovies(query));
tableView.setItems(observableMovieList);
}
私有ArrayList filterMovies(字符串查询){
ArrayList filteredMovies=新的ArrayList();
为(电影:影迷){
if(movie.getTitle().contains(查询)| | movie.getDirector().contains(查询)){
filteredMovies.add(电影);
}
}
返回过滤视频;
}
私人电影{
私有财产所有权;
私人物业董事;
公共电影(字符串标题、字符串导演){
this.title=新的SimpleStringProperty(title);
this.director=新SimpleStringProperty(director);
}
公共字符串getTitle(){
返回title.get();
}
公共财产所有权{
返回标题;
}
公共无效集合标题(字符串标题){
此.title.set(title);
}
公共字符串getDirector(){
return director.get();
}
public StringProperty directorProperty(){
返回董事;
}
公共无效集合控制器(字符串控制器){
此.director.set(director);
}
}
}
搜索电影。fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane prefHeight="610.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lib.controllers.SearchMovies">
   <children>
      <TextField fx:id="searchField" prefHeight="49.0" prefWidth="734.0" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="192.0" AnchorPane.topAnchor="35.0" />
      <Button mnemonicParsing="false" onAction="#search" prefHeight="49.0" prefWidth="155.0" text="SEARCH" AnchorPane.leftAnchor="844.0" AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="35.0" />
      <TableView fx:id="tableView" layoutX="50.0" layoutY="120.0" prefHeight="627.0" prefWidth="974.0" AnchorPane.bottomAnchor="21.0" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="120.0">
        <columns>
          <TableColumn fx:id="titleColumn" prefWidth="75.0" text="Title" />
          <TableColumn fx:id="directorColumn" prefWidth="433.0" text="Director" />
            <TableColumn fx:id="likeColumn" prefWidth="215.0" text="Like" />
        </columns>
         <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>
      </TableView>
   </children>
</AnchorPane>


please..通常,列表可以包含空值,因此一种可能的解释是您传递的列表包含空值。但是没有一个答案是无法知道的。对不起,这个草率的问题。我想出了一个小MRE,如果你们能看一下我会很高兴的!如果还有什么不清楚的地方,请告诉我。如果我不得不猜测,我会说,当这些项目从表中删除时,就会发生这种情况。如果我为
If(getTableRow().getItem()==null)返回添加检查
inside
updateItem()
该程序运行平稳,但我不知道这样做是否合适,因为它感觉有点黑客味,我不知道到底发生了什么。仅供参考:经过一点挖掘,我认为这是一个bug并已归档。在访问行/项时,也有一个关于自动调整大小的NPE-在修复之前,我们需要防止行及其项