我的IDE是Intellij。我尝试了这个文档来学习预加载器,但由于某些原因,预加载器从来没有从我的主类中调用过,甚至它的方法也没有被调用过。
public class LongInitApp extends Application {
Stage stage;
BooleanProperty ready = new SimpleBooleanProperty(false);
private void longStart() {
//simulate long init in background
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
int max = 10;
for (int i = 1; i <= max; i++) {
Thread.sleep(200);
notifyPreloader(new ProgressNotification(((double) i)/max));
}
ready.setValue(Boolean.TRUE);
notifyPreloader(new StateChangeNotification(
StateChangeNotification.Type.BEFORE_START));
return null;
}};
new Thread(task).start();
}
public static void main(String args[]) {
launch(args);
}
@Override
public void start(final Stage stage) throws Exception {
longStart();
stage.setScene(new Scene(new Label("Application started"),400, 400));
ready.addListener(new ChangeListener<Boolean>(){
public void changed(
ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
if (Boolean.TRUE.equals(t1)) {
Platform.runLater(new Runnable() {
public void run() {
stage.show();
}});}}});;}}
public class LongAppInitPreloader extends Preloader {
ProgressBar bar;
Stage stage;
boolean noLoadingProgress = true;
private Scene createPreloaderScene() {
bar = new ProgressBar(0);
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
@Override
public void handleProgressNotification(ProgressNotification pn) {
if (pn.getProgress() != 1.0 || !noLoadingProgress) {
bar.setProgress(pn.getProgress()/2);
if (pn.getProgress() > 0) {
noLoadingProgress = false;
}
}
}
@Override
public void handleStateChangeNotification(StateChangeNotification evt) {
//ignore, hide after application signals it is ready
}
@Override
public void handleApplicationNotification(PreloaderNotification pn) {
if (pn instanceof ProgressNotification) {
double v = ((ProgressNotification) pn).getProgress();
if (!noLoadingProgress) {
v = 0.5 + v/2;
}
bar.setProgress(v);
} else if (pn instanceof StateChangeNotification) {
stage.hide();
}
}
}
您需要在应用程序启动时为其指定预加载器类。一种“快速而肮脏”的方法是使用非公共API类com.sun.javafx.application.launcherimpl
。注意,这个类不能保证在JavaFX的未来版本中可用,所以您应该只使用它进行快速测试(如果有的话)。在LonginitApp
类中使用以下main方法:
public static void main(String[] args) {
LauncherImpl.launchApplication(LongInitApp.class, LongAppInitPreloader.class, args);
}
包含预加载程序的“正式”方法是将其指定为JavaFX部署html" target="_blank">过程的一部分。部署过程的完整文档见http://docs.oracle.com/javase/8/docs/technotes/guides/deploy/,但最小方法如下。
>
在命令行中,使用createjar
命令运行JavaPackager
工具:
javapackager -createjar -outfile myapp.jar -appclass my.package.LongInitApp \
-preloader my.package.LongAppInitPreloader -srcdir dir
其中My.package
是包含应用程序类和预加载器类的包(这些类可以在不同的包中),dir
是包含所有类的目录结构的根目录(例如,如果My.package
确实是您的包名,那么dir
将有一个子目录My
,该子目录将有一个子目录My
,该子目录将包含.class
文件)。
这将生成一个myapp.jar
文件,该文件是可执行的,并且知道预加载程序,因此您可以使用java-jar myapp.jar
执行它。如果您感兴趣,可以从jar文件中提取生成的清单,并使用jar xf myapp.jar meta-inf/manifest.mf
查看其中的内容(然后查看文件meta-inf/manifest.mf
)。(简而言之,这样做就是将主类声明为一个旨在启动JavaFX应用程序的内部类。清单文件包含指定JavaFX应用程序类(在您的例子中为longinitapp
)和预加载器类(如果存在)的属性。启动应用程序的内部类检索这些属性,其main方法基本上启动您定义的应用程序,如果存在预加载器,则使用预加载器。)
注意如果使用这种方法,您的应用程序类LonginitApp
不需要(可能不应该有)main
方法。
大多数IDE对此都有某种形式的支持。例如。如果将Eclipse与E(fx)clipse插件一起使用,并创建一个JavaFX项目,它将为您生成一个build.fxbuild
文件。双击该文件将打开一个可视化编辑器,您可以在其中设置在上面的JavaPackager
命令中定义的属性。单击“Generate ant build.xml and run”将创建jar文件。
除非您需要预加载程序提供的特定功能,超出了您可以轻松编程的功能,否则可能不值得为此付出努力。具体地说,如果通过Java Web Start部署应用程序,并且下载主jar文件需要很长时间,那么预加载器特别有用。预加载程序可以在发生时显示出来。如果您使用的是独立的应用程序(或自包含的应用程序包),那么您可以非常容易地自己创建“预加载器”功能。
例如,除非我使用的是Java Web Start,并且主jar文件很大,否则我可能会重构示例代码,使“预加载器”只是一个常规的旧类:
import javafx.scene.Scene;
import javafx.beans.property.DoubleProperty ;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class LongAppInitPreloader {
private ProgressBar bar;
private Stage stage;
public LongAppInitPreloader() {
this.stage = new Stage();
stage.setScene(createPreloaderScene());
}
private Scene createPreloaderScene() {
bar = new ProgressBar(0);
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
public void show() {
stage.show();
}
public void hide() {
stage.hide();
}
public DoubleProperty progressProperty() {
return bar.progressProperty();
}
}
然后应用程序类就可以使用任务并更新其进度:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
public class LongInitApp extends Application {
@Override
public void start(final Stage stage) throws Exception {
Task<Void> task = createLongStartTask();
stage.setScene(new Scene(new Label("Application started"), 400, 400));
LongAppInitPreloader preloader = new LongAppInitPreloader();
preloader.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(e -> {
stage.show();
preloader.hide();
});
preloader.show();
new Thread(task).start();
}
private Task<Void> createLongStartTask() {
// simulate long init in background
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
int max = 10;
for (int i = 1; i <= max; i++) {
Thread.sleep(200);
updateProgress(i, max);
}
return null;
}
};
return task ;
}
// just here so I can run directly from Eclipse:
public static void main(String args[]) {
launch(args);
}
}
有什么潜在的解决方案吗?
我正在使用Scene Builder2.0和eclipse Luna。在fxml文件中,我有我的场景的代码和图像。如果我在eclipse上测试这一点,一切都是正常的,但是如果我将它导出到可运行的jar中,然后运行它,我就会得到没有图像的窗口...以下是部分代码: 文件结构: 我觉得问题出在路径上,但我不知道这条路是怎么走的。加载程序代码: 初始化函数:
我正在尝试在javaFx中为特殊需要定制一个快捷方式系统。 这种特殊需求使得不可能使用KeyCombinaison(只限制一个键修饰符是不可接受的)。 我已经做了我适当的KeyCompin联络员系统,现在我想从节点调用一个处理程序(我在控制器之外)。但是我找不到任何优雅的解决方案来执行这个。 有一个按钮声明: 在我想从我的快捷方式代码调用控制器的操作之后。 和标准控制器。 我可以做一些工作,例如使
问题内容: 在Java 8中,我可以使用以下方法使用预加载器启动JavaFX应用程序: 我更喜欢从上面的代码开始,而不是使用部署配置,因为我不希望图形界面在每次启动应用程序时都启动,而只是在一些计算出应用程序应该在其中运行的代码之后才启动GUI模式。 我使用的是“ com.sun.javafx.application.LauncherImpl”类,但显然在Java 9中,所有以“ com.sun”
所以我试图安装一个名为better sqlite pool的节点包,但是我遇到了一个似乎无法解决的错误。每当我运行npm I better sqlite池时,都会出现以下错误: 我对此做了广泛的研究,并尝试了几乎所有建议的修复方法,但都没有成功。 我通过添加环境变量VCTargetsPath并将其设置为C:\Program Files(x86)\MSBuild\Microsoft,成功修复了收到的