JavaFXListView自定义单元格
我尝试为ListView创建自定义单元格,但没有显示任何内容 在我的菜单控制器中,我使用的ListView必须包含以下项目: FXML只是一个要测试的空白页:JavaFXListView自定义单元格,listview,javafx,fxml,Listview,Javafx,Fxml,我尝试为ListView创建自定义单元格,但没有显示任何内容 在我的菜单控制器中,我使用的ListView必须包含以下项目: FXML只是一个要测试的空白页: <AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHe
<AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.exalow.easymind.ui.factory.ProjectCell" />
FXML是一个基本的空白锚地窗格:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.exalow.easymind.ui.controllers.ProjectCellController" />
你的代码有很多问题 您正在为每个单元格分配相同的单元格实例,因为您的单元格工厂每次调用时都返回相同的实例。这违反了UI元素只能添加到场景图一次的规则。 如果在空单元格上调用updateItem,则将图形设置为null。在任何情况下,您都不会将图形设置回任何其他内容。因此,如果某个单元格曾经用作空单元格,并且这种情况通常在首次创建或显示ListView时发生,则该单元格将始终没有内容,即使它后来变为非空。 控制器通常不应该是UI组件。此规则有一些例外情况,例如使用,但这通常是一个坏主意,因为它会混淆控制器和视图。 因此,这里的策略应该是将单元工厂设置为创建新单元实例的工厂。该单元格可以在构造函数中加载FXML文件,这样每个单元格都会加载UI的新实例,但每个单元格只加载一次。在updateItem方法中,如果单元格为空,则将图形设置为null,否则根据项目配置控制器,并将图形设置为从FXML加载的UI 比如:
public class ProjectCellController {
@FXML
private AnchorPane root;
@FXML
private ImageView imageView;
@FXML
private Label nameLabel;
@FXML
private Label descriptionLabel;
@FXML
private Label createDateLabel;
public void setProject(Project project) {
if (project.hasImage()) {
imageView.setImage(new Image(project.getImageUrl()));
} else imageView.setImage(new Image(project.getDefaultImage()));
nameLabel.setText(project.getName());
descriptionLabel.setText(project.getDescription());
createDateLabel.setText(project.getCreateDate().toString());
}
}
然后
以下是一个简化但完整的示例:
Project.java:
public class Project {
private final String name ;
public Project(String name) {
this.name = name ;
}
public String getName() {
return name ;
}
}
Main.fxml:
MainController.java:
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
public class MainController {
@FXML
private ListView<Project> list ;
public void initialize() {
for (int i = 1 ; i <= 100 ; i++) {
list.getItems().add(new Project("Project "+i));
}
list.setCellFactory(lv -> new ProjectCell());
}
}
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class ProjectCellController {
@FXML
private Label nameLabel ;
public void setProject(Project project) {
nameLabel.setText(project.getName());
}
}
以及主要应用程序类:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class App extends Application {
@Override
public void start(Stage stage) throws IOException {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("Main.fxml")), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
请在问题中发布看起来不像控制器的控制器和FXML,而不是作为单独的链接。这看起来像是你在每个单元格中尝试使用相同的UI实例,这肯定不起作用。我已经按照你说的做了,但像以前一样没有错误,但什么都没有出现。。。IDK怎么办:@Exalow那么你需要在问题中发布一个实际值,以便其他人可以复制、粘贴并运行它来查看问题。@Exalow它对我来说很好:我发布了一个完整的示例,你可以测试它。没有人能真正帮助你,如果没有一个完整的例子,你需要发布一个完整的例子,我们可以复制和运行。我不知道你有什么不明白的。我在我的回答中发布了一个完整的示例,您可以复制并运行它,并验证它是否有效。我不知道你还指望其他人做什么。哦,天哪。。。3个小时后,我发现这是因为我的列表视图是最终的,我想哭。感谢您的帮助:
public class ProjectCell extends ListCell<Project> {
private AnchorPane root ;
private ProjectCellController controller ;
public ProjectCell() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/fxml/ProjectCell.fxml"));
root = loader.load();
controller = loader.getController();
} catch (IOException exc) {
// this is basically fatal, so just bail here:
throw new RuntimeException(exc);
}
}
@Override
protected void updateItem(Project project, boolean empty) {
super.updateItem(project, empty);
if (empty || project == null) {
setGraphic(null);
} else {
controller.setProject(project);
setGraphic(root);
}
}
}
projectListView.setCellFactory(listView -> new ProjectCell());
public class Project {
private final String name ;
public Project(String name) {
this.name = name ;
}
public String getName() {
return name ;
}
}
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
public class MainController {
@FXML
private ListView<Project> list ;
public void initialize() {
for (int i = 1 ; i <= 100 ; i++) {
list.getItems().add(new Project("Project "+i));
}
list.setCellFactory(lv -> new ProjectCell());
}
}
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.ListCell;
public class ProjectCell extends ListCell<Project> {
private Parent root ;
private ProjectCellController controller ;
public ProjectCell() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ProjectCell.fxml"));
root = loader.load();
controller = loader.getController() ;
} catch (IOException exc) {
throw new RuntimeException(exc);
}
}
@Override
protected void updateItem(Project project, boolean empty) {
super.updateItem(project, empty);
if (empty || project==null) {
setGraphic(null);
} else {
controller.setProject(project);
setGraphic(root);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<VBox xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ProjectCellController">
<children>
<Label fx:id="nameLabel" />
</children>
</VBox>
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class ProjectCellController {
@FXML
private Label nameLabel ;
public void setProject(Project project) {
nameLabel.setText(project.getName());
}
}
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class App extends Application {
@Override
public void start(Stage stage) throws IOException {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("Main.fxml")), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}