title: Opening a modal JavaFX Alert from Swing Frame
body: <p>I am currently working on a project that uses a framework that is based on swing. My goal is to add a JavaFX component to this project, but I am having some problems with modal dialogs.</p>
  
  <p>Overall my problem can be simplified as follows -</p>
  
  <p>Swing: I have a <code>JFrame</code> containing a button. When I press this button, I want to open a dialog containing some JavaFX code. This new dialog should block and always be on top of the frame.</p>
  
  <p>JavaFX: Here I also have a button. When I press this button, I want to display an <code>Alert</code> which should block the Dialog (and therefore also the Swing JFrame).</p>
  
  <p>Currently my solution is to use a <code>JDialog</code> containing a <code>JFXPanel</code> as "glue" so overall my logic is as follows</p>
  
  <ul>
  <li>The <code>JFrame</code> contains a button that opens a new <code>JDialog</code></li>
  <li>This <code>JDialog</code> contains a <code>JFXPanel</code> which contains a JavaFX <code>Scene</code> containing a JavaFX <code>Button</code></li>
  <li>Pressing this JavaFX <code>Button</code> opens an <code>Alert</code></li>
  </ul>
  
  <p>The code is in the bottom of this post.</p>
  
  <p>Currently the <code>JDialog</code> works as expected. It blocks the parent frame and is always on top of it.</p>
  
  <p>The JavaFX <code>Dialog</code> on the other hand, doesn't work quite as expected. It does block the JavaFX <code>Scene</code> (I am not able to press the button multiple times), but it has some problems with the <code>JDialog</code>. These are -</p>
  
  <ol>
  <li>It is not always on top of it. I am able to bring the <code>JDialog</code> on front of my alert</li>
  <li>It doesn't block it. I am able to close the <code>JDialog</code> using the X</li>
  </ol>
  
  <p>My own theory is that the problem is the relation between the <code>JDialog</code> and the <code>JFXPanel</code>. But I am not quite sure how to link them.</p>
  
  <p>A quick and dirty example:</p>
  
  <pre><code>package test;
  
  import java.awt.Dialog.ModalityType;
  import java.awt.Frame;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.lang.reflect.Field;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javafx.application.Platform;
  import javafx.embed.swing.JFXPanel;
  import javafx.event.EventHandler;
  import javafx.scene.Scene;
  import javafx.scene.control.Alert;
  import javafx.scene.control.Alert.AlertType;
  import javafx.scene.control.Button;
  import javafx.scene.layout.StackPane;
  import javafx.stage.Modality;
  import javafx.stage.Window;
  import javax.swing.JButton;
  import javax.swing.JDialog;
  import javax.swing.JFrame;
  
  
  public class TestFXInSwing {
  
  private static void createAndShowGUI() {
  
      JFrame frame = new JFrame("JFrame");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
      JButton button = new JButton("Open JDialog With JFXPanel");
  
      button.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent event) {
              System.err.println("Opening JFXPanel");
  
              JDialog dialog = new JDialog(frame, "JDialog");
              final JFXPanel fxPanel = new JFXPanel();
              dialog.setModal(true);
  
              dialog.setModalityType(ModalityType.APPLICATION_MODAL);
  
              dialog.add(fxPanel);
  
              Platform.setImplicitExit(false);
              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      initFX(fxPanel);
                  }
  
                  private void initFX(JFXPanel fxPanel) {
                      Button btn = new Button("Open JavaFX Alert");
  
                      btn.setOnAction(new EventHandler&lt;javafx.event.ActionEvent&gt;() {
  
                          @Override
                          public void handle(javafx.event.ActionEvent t) {
                              System.err.println("Javafx button pressed");
  
                              Alert alert = new Alert(AlertType.INFORMATION);
                              alert.setTitle("Javafx Alert");
                              alert.setHeaderText("Look, an Information Dialog");
                              alert.setContentText("I have a great message for you!");
                              alert.initModality(Modality.APPLICATION_MODAL);
  
                              Field f;
                              try {
                                  f = JFXPanel.class.getDeclaredField("stage");
                                  f.setAccessible(true);
                                  alert.initOwner((Window) f.get(fxPanel));
                              } catch (NoSuchFieldException ex) {
                                  Logger.getLogger(TestFXInSwing.class.getName()).log(Level.SEVERE, null, ex);
                              } catch (SecurityException ex) {
                                  Logger.getLogger(TestFXInSwing.class.getName()).log(Level.SEVERE, null, ex);
                              } catch (IllegalArgumentException ex) {
                                  Logger.getLogger(TestFXInSwing.class.getName()).log(Level.SEVERE, null, ex);
                              } catch (IllegalAccessException ex) {
                                  Logger.getLogger(TestFXInSwing.class.getName()).log(Level.SEVERE, null, ex);
                              }
                              alert.showAndWait();
                          }
                      });
  
                      StackPane root = new StackPane();
                      root.getChildren().add(btn);
  
                      Scene scene = new Scene(root, 500, 500);
                      fxPanel.setScene(scene);
                  }
              });
  
              dialog.setVisible(true);
          }
  
      });
  
      frame.getContentPane().add(button);
  
      //Display the window.
      frame.pack();
      frame.setVisible(true);
  }
  
  public static void main(String[] args) {
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
              createAndShowGUI();
          }
      });
  }
  }
  </code></pre>