我是 JavaFX 的新手(仍在学习),目前正在研究 TableViews 主题。我关注了这个特定的 YouTube 视频,其中他制作了一个有关将单元格插入到 TableView 的程序,并且该程序对他来说非常顺利。我跟着做了,一切看起来都很好,编辑器中没有错误,只是在运行时遇到错误。错误显示:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at [email protected]/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at [email protected]/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1135)
Caused by: java.lang.RuntimeException: Exception in Application start method
at [email protected]/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
at [email protected]/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: javafx.fxml.LoadException:
/C:/Users/Mako/Documents/Programming/Eclipse-workspace2/JavaFXTable/bin/application/Scene1.fxml
at [email protected]/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2722)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2700)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3376)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3332)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3300)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3272)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3248)
at [email protected]/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3241)
at JavaFXTable/application.Main.start(Main.java:16)
at [email protected]/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
at [email protected]/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at [email protected]/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at [email protected]/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
... 1 more
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TableColumn.setCellValueFactory(javafx.util.Callback)" because "this.name" is null
at JavaFXTable/application.Scene1Controller.initialize(Scene1Controller.java:32)
at [email protected]/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2670)
... 17 more
Exception running application application.Main
这些是我当前包中的代码,全部包含在一个包中。 Main.java
package application;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
@Override
public void start(Stage stage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Scene1.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Scene1Controller.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
public class Scene1Controller implements Initializable{
@FXML
private TableColumn<Food, String> name;
@FXML
private TableColumn<Food, Integer> price;
@FXML
private TableView<Food> table;
ObservableList<Food> list = FXCollections.observableArrayList(
new Food("Pizza", 10),
new Food("IcedCream", 5)
);
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
name.setCellValueFactory(new PropertyValueFactory<Food, String>("name"));
price.setCellValueFactory(new PropertyValueFactory<Food, Integer>("price"));
table.setItems(list);
}
}
Food.java
package application;
public class Food {
String name;
int price;
public Food(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
场景1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Scene1Controller">
<children>
<TableView fx:id="table" layoutX="200.0" layoutY="14.0" prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn fx:id="name" prefWidth="75.0" text="name" />
<TableColumn fx:id="price" prefWidth="75.0" text="price" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</AnchorPane>
希望有人能帮忙,祝你有美好的一天!
我尝试关注具有相同主题的其他视频,但无济于事。
PropertyValueFactory
没有理由更喜欢使用 PropertyValueFactory
而不是基于 lambda 的高级解决方案。参见:打开您的包裹
javafx.base
进行反思
PropertyValueFactory
在模块化应用程序中工作,并由提问者在评论中确认:
我尝试通过将只要我的
module-info.java
添加到javafx.base
部分来修改opens application to
文件,并且成功运行。
opens
中有适当的
module-info.java
子句,您的代码对我来说也运行良好(表格显示并按预期填充)。如果我通过从 FXML 中删除属性
fx:id="name"
来修改您提供的 FXML,它将失败并出现与您在问题中指出的相同错误消息。否则,它将失败,如下所示,直到
module-info.java
设置正确的值。来自 javadoc:
模块访问问题会产生警告消息:将应用程序部署为模块
如果引用的类位于命名模块中,那么它必须是 可以通过反射方式访问
javafx.base
模块。一个类是 如果模块打开包含的包以进行反射访问 至少是 javafx.base 模块。否则 call(TableColumn.CellDataFeatures
) 方法将记录警告并 返回空值。例如,如果
Person
类位于com.foo
包中foo.app
模块,module-info.java
可能看起来像这样:module foo.app { opens com.foo to javafx.base; }
或者,如果模块导出包含包,则可以反射访问类 无条件的。
WARNING: Can not retrieve property 'name' in PropertyValueFactory: javafx.scene.control.cell.PropertyValueFactory@109ad50a with provided class type: class application.Food
以及具有以下原因的堆栈跟踪:
Caused by: java.lang.IllegalAccessException: module javafx.base cannot access class application.Food (in module <your module>) because module <your module> does not open application to javafx.base