使用 jpackage 为具有 css 文件的程序创建安装程序

问题描述

我在使用 jpackage 打包程序时遇到的问题需要帮助。该程序是在 Eclipse 中创建的非模块化 JavaFX 应用程序。在 Eclipse 中,应用程序可以准确地编译和运行。但是当我使用命令提示符进行编译和运行时,编译工作但应用程序不再运行。我收到以下错误消息:

java.lang.NullPointerException:无法调用 “java.net.URL.toExternalForm()”因为返回值 “java.lang.class.getResource(String)”为空 在 application.Main.start(Main.java:158) 在 javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428) 在 java.base/java.security.AccessController.doPrivileged(AccessController.java:391) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427) 在 javafx.graphics/com.sun.glass.ui.invokelaterdispatcher$Future.run(invokelaterdispatcher.java:96) 在 javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native 方法) 在 javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174) 在 java.base/java.lang.Thread.run(Thread.java:832)

尽管如此,jpackage 会创建一个没有任何错误或警告消息的安装程序。使用创建的安装程序进行安装也可以正常工作。但是当我启动我的应用程序时,我的 GUI 不会显示。更准确地说:GUI 的第一部分是一些使用标准布局的设置窗口。显示设置窗口,但不显示“主”GUI。因此,我认为问题的根源在于缺少 css 文件。 我的假设是否正确,如果是:我该如何解决

提前致谢!

附录:这是我的命令提示符输入:

  1. dir /s /b *.java > 源文件.txt

  2. javac --module-path %PATH_TO_FX% --add-modules javafx.controls,javafx.fxml –d out @sources.txt

  3. java --module-path %PATH_TO_FX% --add-modules javafx.controls,javafx.fxml –cp out application.Main(这里出现错误

  4. jar --create --file=libs/sample1.jar --main-class=application.Main –C out .

  5. %JAVA_HOME%\bin\jpackage --type exe –i libs --main-jar sample1.jar –n Sample1 --module-path %PATH_TO_FX_MODS% --add-modules javafx.controls,javafx. fxml --main-class application.Main --win-shortcut --win-menu --win-dir-chooser

css-file 与 main-class 位于同一目录中。

解决方法

谢谢你的提示。我仔细阅读了带有链接的手册。现在我明白我的代码可能有问题。之前我认为 jpackage 和我在命令提示符中的命令有问题。与此同时,我重新编写了代码并用 URL-classes 替换了 File-classes。但我仍然遇到类似的错误。因此我写了一个新的(简单的)代码来重现错误。

package application;
    
import java.io.BufferedReader;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,600,500);
            URL urlImage = getClass().getResource("image.jpg");
            Image image = new Image(urlImage.toExternalForm(),400,true,true);
            ImageView imageView = new ImageView(image);
            root.setCenter(imageView);
            
            Label headline = new Label("Example Image");
            URL urlStyles = getClass().getResource("styles.css");
            headline.getStylesheets().add(urlStyles.toExternalForm());      
            root.setTop(headline);
            
            Button button = new Button();
            URL urlFile = getClass().getResource("text.txt");
            String temp = urlFile.toString().replaceFirst("file:/","");
            button.setText(read(temp));
            root.setBottom(button);         
            
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    
    public String read (String file) throws IOException {
        FileReader fileReader = new FileReader(file);
        BufferedReader in = new BufferedReader(fileReader);
        try {           
            String str = in.readLine();
            in.close();
            return str;
        } catch(IOException e) {
            e.printStackTrace();
            return "Error";
        }
    }
}

在使用命令提示符进行编译时,我仍然收到一个错误:

java.lang.NullPointerException:无法调用 "java.net.URL.toExternalForm()" 因为 "" 为空 在 application.Main.start(Main.java:25) 在 javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428) 在 java.base/java.security.AccessController.doPrivileged(AccessController.java:391) 在 javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427) 在 javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96) 在 javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native 方法) 在 javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174) 在 java.base/java.lang.Thread.run(Thread.java:832)

我是否尝试加载图像(代码中的第一段)、css(第二段)或 txt 文件(最后一段)都没有关系。所有这些文件(图片、css、txt)都和主类在同一个目录下。

也许我错过了树林里的森林,但我认为我使用了 URL 类,就像指南解释的那样。我在下面有任何进一步的建议。谢谢!