java - 为什么 getTableRow().getItem() 返回一个空引用,即使不是空行?
问题描述
所以我创建了这个带有搜索栏和表格视图的小应用程序。当屏幕初始化时,我使用tableView.setItems()
将固定的项目列表添加到我的表中。后来,当用户执行查询时,会生成一个过滤列表,我tableView.setItems()
再次调用。当列表被渲染时,我的代码调用方法getRowTable().getItem()
来为每一行的按钮添加行为。一切都正确呈现,但是,似乎updateItem()
被调用的次数超过了它应该被调用的次数,并getRowTable().getItem()
返回一个null
使程序抛出异常的引用。
这是什么原因造成的?代码如下。
应用程序.java
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
URL url = getClass().getResource("/com/lib/fxml/search-movies.fxml");
try {
Parent root = FXMLLoader.load(url);
Scene scene = new Scene(root, 1024, 768);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
launch(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);
}
}
}
搜索-movies.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>
解决方案
推荐阅读
- powershell - 带有从文本文件读取的 Image Magick Montage 的 Powershell
- python - 从列表 python2.7 中检索值
- javascript - 有条件地返回承诺或回调的包装函数
- javascript - 在 FormData 中传递和访问 JSON 对象和 CSV 文件
- angularjs - 数据编辑 - 模态 Bootstrap
- arrays - 二维字符数组打印错误结果
- json - 无法在服务器上打开 Json 文件
- vba - 根据范围和周期循环和打开文件
- javascript - 使用 jQuery 向下滚动页面到锚点不起作用
- r - R绑定到R中的NULL DF