【问题标题】:JavaFX can't load stylesheets: rootPane.getStylesheets().add(url.toString()); causing NullPointerExceptionJavaFX 无法加载样式表:rootPane.getStylesheets().add(url.toString());导致 NullPointerException
【发布时间】:2017-02-09 15:07:28
【问题描述】:

我正在尝试在控制器的 initialize 方法中使用以下代码加载 CSS 样式表:

public class Controller implements Initializable {

    @FXML BorderPane rootPane;
    @FXML TextField txtTest;
    @FXML Button btnSayHey;
    @FXML Button btnLookMa;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        String styleFile = "res/striped-progress.css";
        URL url = getClass().getResource(styleFile);
        rootPane.getStylesheets().add(url.toString());

    }
}

但是在启动应用程序时,有一个 javafx.fxml.LoadException 被抛出并查看堆栈跟踪,我可以看到

rootPane.getStylesheets().add(url.toString());

导致NullPointerException。我的启动方法如下:

@Override
public void start(Stage primaryStage) throws Exception {


    String sceneFile = "scripts/DEV/PLAYGROUND/STYLES/res/MainView.fxml";
    Parent root = null;
    URL    url  = null;

    try
    {
        url = new File(sceneFile).toURI().toURL();
        root = FXMLLoader.load( url );
        System.out.println( "  fxmlResource = " + sceneFile );
    }
    catch ( Exception ex )
    {
        System.out.println( "Exception on FXMLLoader.load()" );
        System.out.println( "  * url: " + url );
        System.out.println( "  * " + ex );
        System.out.println( "    ----------------------------------------\n" );
        throw ex;
    }

    BorderPane page = (BorderPane) root;
    Scene scene = new Scene(page);
    primaryStage.setScene(scene);
    primaryStage.setTitle("SampleCSS App - v1.0");
    primaryStage.show();
}

控制台堆栈跟踪在这里:

    Exception on FXMLLoader.load()
  * url: file:/C:/rangedb/workspaces/UKRangeDBdemo/app_RVSW/scripts/DEV/PLAYGROUND/STYLES/res/MainView.fxml
  * javafx.fxml.LoadException: 
/C:/rangedb/workspaces/UKRangeDBdemo/app_RVSW/scripts/DEV/PLAYGROUND/STYLES/res/MainView.fxml

    ----------------------------------------

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:363)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:303)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:875)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$147(LauncherImpl.java:157)
    at com.sun.javafx.application.LauncherImpl$$Lambda$49/1545327692.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
/C:/rangedb/workspaces/UKRangeDBdemo/app_RVSW/scripts/DEV/PLAYGROUND/STYLES/res/MainView.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3208)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3169)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3142)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3118)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3098)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3091)
    at DEV.PLAYGROUND.STYLES.ExternalStylesSample.start(ExternalStylesSample.java:79)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
    at com.sun.javafx.application.LauncherImpl$$Lambda$52/897256917.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/661672156.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
    at com.sun.javafx.application.PlatformImpl$$Lambda$48/1517660793.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/128893786.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
    at com.sun.glass.ui.win.WinApplication$$Lambda$38/1349277854.run(Unknown Source)
    ... 1 more
Caused by: java.lang.NullPointerException
    at DEV.PLAYGROUND.STYLES.Controller.initialize(Controller.java:49)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2542)
    ... 22 more
Exception running application DEV.PLAYGROUND.STYLES.ExternalStylesSample

您会注意到只需注释掉/删除该行 initialize() 中的 rootPane.getStylesheets().add(url.toString()); 将导致所有错误消失,但这不会加载 CSS 样式表。

更新

在 James_D 的建议下添加包结构:

【问题讨论】:

  • "你会注意到简单地注释掉/删除行......" - 这肯定意味着你已经在 Controller.java 的第 49 行放置了一个断点并检查它是否是 @987654332 @ 或 null 行的其他部分,对吧?
  • 为什么要从文件中加载资源?当您将应用程序捆绑为 jar 文件时,或者如果应用程序使用不同的工作目录运行,这将完全失败。您应该加载资源,而不是文件。
  • @Axel 调试器说 rootPanenull 但它不应该在我使用 FXMLLoader 时被初始化吗?
  • @James_D 这更多是出于绝望。由于我没有将其打包为.jar,因此这本身并不是我的首要任务。
  • 好吧,现在它可能不是优先事项,但大概在某个时候您将它捆绑为一个 jar 文件。当你这样做时,你真的想回去重写所有与资源相关的代码吗?使用资源(即getClass().getResource() 创建 URL 并发布您的项目结构,如果您无法使其正常工作。使用文件作为实际应用程序的一部分肯定会失败。

标签: java css url javafx


【解决方案1】:

(感谢 James_D 的 cmets,我已经设法解决了我自己的问题。所以这里......)

NullPointerException 是由于我没有在我的MainView.fxml 文件中初始化 BorderPane 对象引起的。将fxml文件中BorderPanefx:id设置为rootPane后(注意:这个名称设置为rootPane,因为在我的Controller中,我有一个@FXML注入字段:

@FXML Parent rootPane;

进行此更改后,几乎所有错误都消失了。除了以下运行时警告:

com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not find stylesheet: file:/C:/rangedb/workspaces/UKRangeDBdemo/app_RVSW/res/striped-progress.css

尽管 CSS 在运行时被应用于我的控件。事实证明,只需在返回的URL 对象上使用toExternalForm(),就可以以“特权”方式加载样式表:

getClass().getResource("res/striped-progress.css")

也就是说,我把上面这行代码改成了:

rootPane.getStylesheets().add(getClass().getResource("res/striped-progress.css").toExternalForm());

toExternalForm() 返回 String 表示 URL 对象,但我不确定为什么不使用它会导致警告,而使用它不会。无论哪种方式,它都有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多