让我们使用带有FXML的JavaFX 8创建最简单的Hello World应用程序:
文件
src/application/Main.java
:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
@Override
public void start(Stage stage) {
try {
System.out.println("Main.start()");
FXMLLoader fxml_loader = new FXMLLoader();
fxml_loader.setLocation(getClass().getResource("Sample.fxml"));
System.out.println("FXML resource URL = " + getClass().getResource("Sample.fxml"));
Parent root = fxml_loader.load();
Scene scene = new Scene(root, 300, 200);
stage.setScene(scene);
stage.setTitle("JFX HW");
stage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
src/application/Sample.fxml
:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.StackPane?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Label text="Hello World" />
</children>
</StackPane>
工作流
使用您喜欢的IDE,将所有IDE编译到bin
文件夹中:
$ find bin
bin
bin/application
bin/application/Main.class
bin/application/Sample.fxml
然后创建一个jar:
$ javapackager -createjar -appclass application.Main -srcdir bin -outdir compiled -outfile jfxhw -v -manifestAttrs "Application-Name=JFXHW,Permissions=sandbox,Codebase=*"
可以在此验证jar文件与java -jar jfxhw.jar
一起正常工作。
让我们签名:
$ jarsigner compiled/jfxhw.jar MYALIAS
部署:
$ javapackager -deploy -appclass application.Main -srcdir compiled -outdir deployed -outfile index -width 300 -height 200 -name JFXHW -v
$ find deployed
deployed/
deployed/jfxhw.jar
deployed/index.jnlp
deployed/index.html
结果
命令:
javaws index.jnlp
失败(您需要启用控制台才能看到这个):
Main.start()
FXML resource URL = null
java.lang.IllegalStateException: Location is not set.
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2438)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2413)
at application.Main.start(Main.java:18)
:
我做错了什么?
答案 0 :(得分:5)
应用程序需要足够的权限来调用fxml文件。您尚未在部署步骤中设置任何权限,因此在生成的jnlp文件中省略了安全性部分。
有一个已知的错误,它计划在Java 9中修复。这个错误与你的问题有关,但不是根本原因。
https://bugs.openjdk.java.net/browse/JDK-8088866
对于jarsign和javapackager -signjar的不一致。
将 -allpermissions 参数添加到命令行:
javapackager -deploy -allpermissions -appclass application.Main -srcdir compiled -outdir deployed -outfile index -width 300 -height 200 -name JFXHW -v
但是有一点问题:您的manifest.mf将不包含空类Class-Path标记,因为这是由ant脚本添加的。将弹出Java安全提示,并且在将证书添加到操作系统中受信任的根证书存储区之前,您无法运行该应用程序。
首先我更改了部署任务中的权限以将其设置为提升:
<fx:permissions elevated="true" cacheCertificates="true"/>
第二次我创建了以下build.xml文件并将其放在项目的根目录中。你的jnlp将在文件夹dist中创建。您必须为密钥库设置storepass。和正确的别名和密钥库文件名。 如果你不在窗户上,那么&#34; env&#34;可能不会工作。把它设置为你的jdk。
只需使用&#34; ant default&#34;在项目的根目录中。
<?xml version="1.0" encoding="UTF-8"?>
<project name="App" default="default" basedir="."
xmlns:fx="javafx:com.sun.javafx.tools.ant">
<property environment="env"/>
<property name="build.src.dir" value="src"/>
<!-- <property name="build.resources.dir" value="${build.src.dir}/resources"/> -->
<property name="build.classes.dir" value="classes"/>
<property name="build.dist.dir" value="dist"/>
<target name="default" depends="clean,compile">
<!-- defines the classpath -->
<path id="cp">
<filelist>
<file name="${env.JAVA_HOME}/lib/ant-javafx.jar"/>
<file name="${basedir}" />
</filelist>
</path>
<!-- defines the task with a reference to classpath -->
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
uri="javafx:com.sun.javafx.tools.ant"
classpathref="cp"/>
<fx:application id="appId"
name="jfxHw"
mainClass="application.Main"/>
<!-- Defines the resources needed by the application -->
<fx:resources id="appRes">
<fx:fileset dir="${build.dist.dir}" includes="jfxHw.jar"/>
<!-- <fx:fileset dir="${build.dist.dir}" includes="bsigned_jfxHw.jar"/> -->
</fx:resources>
<!-- Create a jar file -->
<fx:jar destfile="${build.dist.dir}/jfxHw.jar">
<fx:application refid="appId"/>
<fx:resources refid="appRes"/>
<fileset dir="${build.classes.dir}"/>
<fileset dir="${build.src.dir}">
<exclude name="**/*.java"/>
</fileset>
<manifest>
<attribute name="Permission" value="all-permissions"/>
</manifest>
</fx:jar>
<signjar alias="myAlias" keystore="myKeystore.jks"
storepass="******"
preservelastmodified="true">
<path>
<fileset dir="${build.dist.dir}" includes="**/*.jar" />
</path>
</signjar>
<fx:deploy width="600" height="400" outdir="${basedir}//${build.dist.dir}/"
outfile="jfxhw" verbose="true">
<fx:info title="jfxHw"/>
<fx:application refid="appId"/>
<fx:resources refid="appRes"/>
<fx:permissions elevated="true" cacheCertificates="true"/>
</fx:deploy>
</target>
<!-- Removes the folders of previous runs -->
<target name="clean">
<mkdir dir="${build.classes.dir}"/>
<mkdir dir="${build.dist.dir}"/>
<delete>
<fileset dir="${build.classes.dir}" includes="**/*"/>
<fileset dir="${build.dist.dir}" includes="**/*"/>
</delete>
</target>
<!-- Compiles the sources -->
<target name="compile" depends="clean">
<javac includeantruntime="false"
srcdir="${build.src.dir}"
destdir="${build.classes.dir}"
fork="yes"
executable="${env.JAVA_HOME}/bin/javac"
source="1.8"
debug="on">
</javac>
</target>
</project>
这是在完成所有操作后创建的。请注意,我将清单权限设置为all-permissios以进行调试。您可以安全地将其设置为沙箱。
Manifest-Version: 1.0
JavaFX-Version: 8.0
Permission: all-permissions
Class-Path:
Created-By: JavaFX Packager
Main-Class: application.Main
Name: application/Sample.fxml
SHA-256-Digest: eT8+7c2XeVhURexj5X9Y1xAP2H8YIMcieeySOmgOPZw=
Name: application/Main.class
SHA-256-Digest: Md+alMOmoQpslZIgLwbmPFAI8axSKBVvReXZFgoKJ6A=
观察安全部分:
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0" xmlns:jfx="http://javafx.com" href="jfxhw.jnlp">
<information>
<title>jfxHw</title>
<vendor>Unknown vendor</vendor>
<description>Sample JavaFX 2.0 application.</description>
<offline-allowed/>
</information>
<resources>
<j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
<jar href="jfxHw.jar" size="3089" download="eager" />
</resources>
<security>
<all-permissions/>
</security>
<jfx:javafx-desc width="600" height="400" main-class="application.Main" name="jfxHw" />
<update check="background"/>
</jnlp>