我正在尝试从JavaFX应用程序中创建一个JFrame窗口。我正在使用Oracle Java 8,我能够在Linux,Windows中做我需要的事情,但在Mac OS中却不能。这似乎是一个JVM实现问题。以下是我的要求:
我在下面创建了示例应用程序。应用程序在Linux和Windows下工作正常,但在Mac OS中,当我尝试等待JFrame线程完成应用程序冻结并且不显示JFrame时。SwingUtilities.invokeLater 不会冻结,但不会等待 JFrame 线程完成。由于我需要等待JFrame线程调用Later对我来说不是一个选择。
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();
}
}
}
}
sample.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();
}
}
}
主类
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()方法的time循环,但它的行为也像Thread.join()。我如何才能实现我的需求?
您可以使用其中一个同步类,如<code>CountDownLatch</code>。将其传递给可运行
并调用锁存器。倒计时()
在<code>run()方法的末尾。同时,您的JavaFX线程将暂停在<code>latch.await()</code>上。然而,这将冻结JavaFXUI,因此这可能不是您想要的。
另一种选择是使用回调。类似于:
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线程等待,但它确实允许您在适当的时间做出反应。您可以将onFinish
的类型更改为您需要的任何类型;例如消费者
如果您想将回调传递给某个对象。
我正在我的UI线程中调用一个方法。在这个方法中创建了一个新线程。我需要UI线程等待这个新线程完成,因为我需要这个线程的结果来继续UI线程中的方法。但我不想让UI在等待时冻结。有没有办法让UI线程在不忙的情况下等待?。
问题内容: 因此,我有一些代码等待X发生,然后创建一个线程并执行processEmail。 我正在寻找的是一种代码,即使processEmail在另一个线程中发生,代码也可以继续等待X,但是当前代码只是等待线程完成,然后再等待X再次发生。 编辑:仅供参考,我什么都不需要在下面的代码中进一步输出processEmail.main(),因此不需要我等待其输出。 由Jean提供的答案:移除main之后的
我想暂停在JavaFX应用程序线程上执行方法并等待用户与UI交互。不要冻结UI很重要。 例子: 我应该如何实现< code>pause()和< code>resume()方法?< br >事件处理程序的执行应在< code>pause()处等待;调用,直到用户按下< code>resume按钮并且调用< code>resume方法。
但这一个也不起作用。正确的答案是加入线程并删除2个睡眠: 我的问题是:为什么我的答案都不能被接受?我的实验室领导问,但他不能给我一个答案。在家里编写了测试代码,它似乎工作得很好。提前感谢您的帮助!
问题内容: 有什么方法可以简单地等待所有线程处理完成?例如,假设我有: 如何更改此方法,以便该方法在注释处暂停直到所有线程的方法退出?谢谢! 问题答案: 你将所有线程放入数组中,全部启动,然后进行循环 每个连接将阻塞,直到相应的线程完成为止。线程的完成顺序可能不同于你加入线程的顺序,但这不是问题:退出循环时,所有线程均已完成。
我打算在主线程中启动2个线程,主线程应该等到所有2个子线程完成,我就是这样做的。 在上面的代码中,确实让主线程等待子线程,但问题是,在第一个线程完成之前不会创建第二个线程。这不是我想要的。 我想要的是,这两个线程立即在主线程中创建,然后主线程等待它们完成。似乎做不到,是吗? 我想,也许我可以通过一个信号灯来完成这项工作,但还有别的方法吗?