为 TableView 列设置单元格值时出错

问题描述 投票:0回答:1

我是 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>

希望有人能帮忙,祝你有美好的一天!

我尝试关注具有相同主题的其他视频,但无济于事。

java javafx
1个回答
0
投票

建议:根本不要使用
PropertyValueFactory

使用 Java 9+(例如任何现代 Java 版本)时,

没有理由更喜欢使用 PropertyValueFactory

 而不是基于 lambda 的高级解决方案。参见:

  • 为什么我应该避免在 JavaFX 中使用 PropertyValueFactory?
打开您的包裹

javafx.base
进行反思

允许

PropertyValueFactory

 在模块化应用程序中工作,并由提问者在评论中确认:

我尝试通过将

module-info.java

 添加到 
javafx.base
 部分来修改 
opens application to
 文件,并且成功运行。

只要我的

opens

 中有适当的 
module-info.java
 子句,您的代码对我来说也运行良好(表格显示并按预期填充)。

如果我通过从 FXML 中删除属性

fx:id="name"

 来修改您提供的 FXML,它将失败并出现与您在问题中指出的相同错误消息。否则,它将失败,如下所示,直到 
module-info.java
 设置正确的值。

来自

PropertyValueFactory

 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
    
© www.soinside.com 2019 - 2024. All rights reserved.