java 如何停止“JavaFX 应用程序线程”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15808063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to stop "JavaFX Application Thread"
提问by Francesco
I have a simple console application which sometimes need to perform graphics operations, for those I'm using JavaFx framework (there are some functions that I need like the css styling for text ) I simply generate some shapes and text into an hidden scene then save those on file and that's all,
我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我使用 JavaFx 框架的应用程序(我需要一些功能,例如文本的 css 样式)我只需将一些形状和文本生成到隐藏场景中然后保存档案中的那些,仅此而已,
I know that to work with JavaFx I have to pass graphics operations to the JavaFx thread, but when everything is done and I have to close the application (after some hours) this JavaFx thread still remain open... and I really don't want to force exit with System.exit() because if something is blocked I may want to know/wait (ALSO I don't want to execute everything as an JavaFx application (as JavaFx components are less than 1% of my main application)
我知道要使用 JavaFx,我必须将图形操作传递给 JavaFx 线程,但是当一切都完成并且我必须关闭应用程序时(几个小时后),这个 JavaFx 线程仍然保持打开状态......我真的没有想使用 System.exit() 强制退出,因为如果某些内容被阻止,我可能想知道/等待(另外我不想将所有内容作为 JavaFx 应用程序执行(因为 JavaFx 组件不到我的主应用程序的 1%)
the code is very simple and googling around I've found only to use
代码非常简单,我发现只能使用谷歌搜索
Platform.exit();
which doesn't seems to work, I've also tried playing with Platform parameters like
这似乎不起作用,我也尝试过使用平台参数,例如
Platform.setImplicitExit(false);
here is my test application which you can run :
这是我可以运行的测试应用程序:
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");
}
}
and this is the thread which never close
这是永远不会关闭的线程
"Attach Listener" - Thread t@17 java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"JavaFX Application Thread" - Thread t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) at java.lang.Thread.run(Thread.java:722)
Locked ownable synchronizers: - None
“附加侦听器” - 线程 t@17 java.lang.Thread.State: RUNNABLE
锁定的可拥有同步器: - 无
“JavaFX 应用程序线程” - 线程 t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3 $1.run(GtkApplication.java:82) 在 java.lang.Thread.run(Thread.java:722)
锁定的可拥有同步器: - 无
Update:I'm using latest Oracle JDK 7u17 64bit on Linux Fedora 16 64bit.
更新:我在 Linux Fedora 16 64 位上使用最新的 Oracle JDK 7u17 64 位。
回答by durron597
Fix:
使固定:
I was able to fix this problem by calling com.sun.javafx.application.PlatformImpl.tkExit()
immediately before Platform.exit()
. I don't really understand the JavaFX source that well, but it seems to be working; YMMV.
我能够通过com.sun.javafx.application.PlatformImpl.tkExit()
在Platform.exit()
. 我不太了解 JavaFX 源代码,但它似乎有效;天啊。
Update:Doing this in Java 8 will produce a warning, you can just turn the warning off with @SuppressWarnings("restriction")
. It shouldn't be a problem.
更新:在 Java 8 中执行此操作会产生警告,您可以使用@SuppressWarnings("restriction")
. 这应该不是问题。
Explanation:
解释:
I figured this out by digging through the source code; JFXPanel
has this little snippet (this is from JavaFX 2.2.25)
我通过挖掘源代码发现了这一点;JFXPanel
有这个小片段(这是来自 JavaFX 2.2.25)
finishListener = new PlatformImpl.FinishListener() {
public void idle(boolean paramAnonymousBoolean) {
if (!JFXPanel.firstPanelShown) {
return;
}
PlatformImpl.removeListener(JFXPanel.finishListener);
JFXPanel.access2(null);
if (paramAnonymousBoolean)
Platform.exit();
}
public void exitCalled()
{
}
The problem is, if you are using only a little bit of JavaFX in your application, then the idle(boolean)
method never does anything (because firstPanelShown == false
), which prevents the listener from getting removed, which prevents the JavaFX Toolkit
from shutting down... which means you have to shut it down manually.
问题是,如果您在应用程序中只使用了一点点 JavaFX,那么该idle(boolean)
方法从不执行任何操作(因为firstPanelShown == false
),这会阻止侦听器被删除,从而阻止 JavaFXToolkit
关闭……这意味着您有手动关闭它。
回答by LeonidVlad
Your main function does not belong to the JavaFx Application object and i think that your program never eneter application thread loop.
您的 main 函数不属于 JavaFx Application 对象,我认为您的程序永远不会进入应用程序线程循环。
It seems you should do:
看来你应该这样做:
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
}
}
回答by Michael Oberlin
That's a slippery situation, as (to my understanding) the purpose of the JavaFX thread is to take advantage of various hardware pipelines transparently. Might I suggest placing your JavaFX requests in a separate, referenced, project; and keep everything else, including your main method, in another? That's always worked for me.
这是一个棘手的情况,因为(据我所知)JavaFX 线程的目的是透明地利用各种硬件管道。我是否建议将您的 JavaFX 请求放在一个单独的、引用的项目中;并将其他所有内容(包括您的主要方法)保存在另一个中?那总是对我有用。
Basically, business logic and model go in one project, and view and control (generally JavaFX-based) go in the other. This allows for independent termination of the JavaFX thread. Hopefully that is applicable to what you are trying to do.
基本上,业务逻辑和模型在一个项目中,视图和控制(通常基于 JavaFX)在另一个项目中。这允许独立终止 JavaFX 线程。希望这适用于您正在尝试做的事情。
回答by Wingie
I tried a lot of things on this as none of the above answers worked for me. Best thing for me was to just shutdown the whole JVM using
我在这方面尝试了很多事情,因为上述答案都不适合我。对我来说最好的事情就是关闭整个 JVM 使用
System.exit(1);
as my whole Application is just that one JavaFX application and therefor can be shut down, when closing the Stage. The 1 in my case is just a random int.
因为我的整个应用程序只是一个 JavaFX 应用程序,因此可以在关闭舞台时关闭。在我的例子中 1 只是一个随机整数。