簡體   English   中英

如何在JavaFX應用程序內部等待JFrame線程完成?

[英]How to wait for a JFrame thread to finish from inside a JavaFX application?

我正在嘗試從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();
            }
        }
    }
}

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();
        }
    }
}

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線程等待,但它確實允許您在適當的時間做出反應。 您可以將onFinished的類型更改為onFinished的任何內容。 例如Consumer如果您想傳遞回調某些對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM