gpt4 book ai didi

java - 如何在 JavaFX 应用程序内部等待 JFrame 线程完成?

转载 作者:行者123 更新时间:2023-12-02 11:08:02 24 4
gpt4 key购买 nike

我正在尝试从 JavaFX 应用程序内部创建 JFrame 窗口。我正在使用 Oracle Java 8,我可以在 Linux、Windows 中执行我需要的操作,但不能在 Mac OS 中执行。看起来像是 JVM 实现问题。这是我的要求:

  • 我需要调用一个创建游戏窗口的库方法(JFrame 的扩展类)。我需要能够在游戏中使用键盘。
  • 我可以访问该库的源代码,但我无意更改该库的源代码
  • 我需要在游戏结束后处理游戏信息,所以我的主线程需要等到游戏结束

我在下面创建了示例应用程序。应用程序在 Linux 和 Windows 下工作正常,但在 Mac OS 中,当我尝试等待 JFrame 线程完成时,应用程序卡住且未显示 JFrame。 SwingUtilities.invokeLater 不会卡住,但不会等待 JFrame 线程完成。因为我需要等待 JFrame 线程,所以 invokeLater 对我来说不是一个选择。

JFrameCreator.java

public class JFrameCreator implements Runnable {
@Override
public void run() {
System.out.println("Creating JFrame");
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setSize(300,300);
frame.setVisible(true);
for (int i = 0; i < 100; i++) {
frame.getContentPane().getGraphics().drawOval(150-i/2,150-i/2,i,i);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

样本.fxml

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Button layoutX="51.0" layoutY="10.0" mnemonicParsing="false" onAction="#createJFrame" text="New JFrame" />
<RadioButton fx:id="cbThread" layoutX="10.0" layoutY="40.0" mnemonicParsing="false" selected="true" text="Thread">
<toggleGroup>
<ToggleGroup fx:id="tg" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="cbInvokeWait" layoutX="10.0" layoutY="60.0" mnemonicParsing="false" text="invokeAndWait" toggleGroup="$tg" />
<RadioButton fx:id="cbInvokeLater" layoutX="10.0" layoutY="80.0" mnemonicParsing="false" text="invokeLater" toggleGroup="$tg" />
</children>
</AnchorPane>

Controller .java

public class Controller {
@FXML RadioButton cbThread;
@FXML RadioButton cbInvokeWait;
@FXML RadioButton cbInvokeLater;

public void createJFrame(javafx.event.ActionEvent actionEvent) {
Runnable r=new JFrameCreator();
try {
if (cbThread.isSelected()) {
Thread t=new Thread(new JFrameCreator());
t.start();
t.join();
}
else if(cbInvokeWait.isSelected())
SwingUtilities.invokeAndWait(r);
else
SwingUtilities.invokeLater(r);
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

Main.java

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Swing in JavaFX");
primaryStage.setScene(new Scene(root, 200, 100));
primaryStage.show();
}


public static void main(String[] args) {
launch(args);
}
}

我还尝试使用 Thread.isAlive() 方法进行 while 循环,但其行为也类似于 Thread.join()。我怎样才能达到我的要求?

最佳答案

您可以使用同步类之一,例如 CountDownLatch 。将其传递给您的 Runnable 并在 run() 方法末尾调用 latch.countDown() 。同时,您的 JavaFX 线程将在 latch.await() 上暂停。但是,这将卡住 JavaFX UI,因此这可能不是您想要的。

另一种选择是使用回调。像这样的东西:

public class JFrameCreator implements Runnable {

private final Runnable onFinished;

public JFrameCreator(Runnable onFinished) {
this.onFinished = onFinished;
}

@Override
public void run() {
// do your work...
Platform.runLater(onFinished); // to communicate to JavaFX Application
// Thread that JFrameCreator is complete
}

}

第二个选项不会导致 JavaFX 线程等待,但它确实允许您在适当的时间使用react。您可以将 onFinished 的类型更改为您需要的任何类型;例如 Consumer 如果您想传递回调某个对象。

关于java - 如何在 JavaFX 应用程序内部等待 JFrame 线程完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50788365/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com