我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我正在使用JavaFx框架的人(我需要一些函数,比如文本的css样式) 我只是在一个隐藏的场景中生成一些形状和文本,然后将它们保存在文件中,这就是全部,
我知道要使用JavaFx我必须将图形操作传递给JavaFx线程,但是当一切都完成后我必须关闭应用程序(几个小时后),这个JavaFx线程仍然保持打开状态......我真的不希望强制退出System.exit()因为如果某些东西被阻止我可能想知道/等待(我不想把所有东西都作为JavaFx应用程序执行(因为JavaFx组件不到我的1%)主要申请)
代码很简单,谷歌搜索我发现只使用
Platform.exit();
这似乎不起作用,我也尝试使用像
这样的平台参数Platform.setImplicitExit(false);
这是我可以运行的测试应用程序:
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;
public class SOTestFX {
public static void main(String[] args) {
SOTestFX t = new SOTestFX();
t.runFxThread();
}
public void runFxThread(){
//Application.launch(args);
final JFXPanel jfxPanel = new JFXPanel();
Platform.runLater(new Runnable() {
@Override
public void run() {
System.err.println("CREATING IMAGE");
simpleFXoperations();
System.err.println("NOW CALL EXIT");
System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW");
Platform.exit();
}
});
try {
Thread.sleep(3000); // just wait a bit if something should happen, let it happen..
} catch (InterruptedException e) {
e.printStackTrace();
}
//jfxPanel.removeNotify(); // return -> java.lang.NullPointerException
//Platform.exit(); // -> does nothing
System.err.println("i will never die!");
}
public void simpleFXoperations(){
VBox vbox1 = new VBox();
vbox1.setAlignment(Pos.BOTTOM_CENTER);
vbox1.setStyle("-fx-border-style: solid;"
+ "-fx-border-width: 1;"
+ "-fx-border-color: white");
System.err.println("simpleFXoperations() _DONE");
}
}
这是永不关闭的主题
“附加侦听器” - 线程t @ 17 java.lang.Thread.State:RUNNABLE
锁定可拥有的同步器: - 没有
“JavaFX Application Thread” - Thread t @ 13 java.lang.Thread.State: RUNNABLE在com.sun.glass.ui.gtk.GtkApplication._runLoop(原生 方法)at com.sun.glass.ui.gtk.GtkApplication $ 3 $ 1.run(GtkApplication.java:82) 在java.lang.Thread.run(Thread.java:722)
锁定可拥有的同步器: - 没有
更新:我在Linux Fedora 16 64位上使用最新的Oracle JDK 7u17 64位。
答案 0 :(得分:25)
我可以在com.sun.javafx.application.PlatformImpl.tkExit()
之前立即致电Platform.exit()
来解决此问题。我不太了解JavaFX源代码,但似乎工作正常; YMMV。
更新:在Java 8中执行此操作会产生警告,您只需使用@SuppressWarnings("restriction")
关闭警告即可。它应该不是问题。
我通过挖掘源代码来解决这个问题; JFXPanel
有这个小片段(来自JavaFX 2.2.25)
finishListener = new PlatformImpl.FinishListener() {
public void idle(boolean paramAnonymousBoolean) {
if (!JFXPanel.firstPanelShown) {
return;
}
PlatformImpl.removeListener(JFXPanel.finishListener);
JFXPanel.access$102(null);
if (paramAnonymousBoolean)
Platform.exit();
}
public void exitCalled()
{
}
问题是,如果你在应用程序中只使用了一点点JavaFX,那么idle(boolean)
方法永远不会做任何事情(因为firstPanelShown == false
),这会阻止侦听器被删除,阻止JavaFX Toolkit
关闭...这意味着你必须手动关闭它。
答案 1 :(得分:2)
您的main函数不属于JavaFx Application对象,我认为您的程序永远不会执行应用程序线程循环。
看来你应该这样做:
public class SOTestFX extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
// Do stuff here to show your stage or whatever you want;
// This will be called on the JavaFX thread
}
}
答案 2 :(得分:2)
这是一个很滑的情况,因为(据我所知),JavaFX线程的目的是透明地利用各种硬件管道。我建议你将JavaFX请求放在一个单独的引用项目中;并保留其他一切,包括你的主要方法,在另一个?这总是对我有用。
基本上,业务逻辑和模型进入一个项目,查看和控制(通常基于JavaFX)进入另一个项目。这允许独立终止JavaFX线程。希望这适用于您要做的事情。