title: How to provide JavaFX components in a dialog in a Swing application?
body: <p>I created a set of JavaFX components in a Scene which I'd like to display in a resizable modal dialog in a swing applications. The JavaFX components include <code>ImageView</code>s for scanned images which can get quite big dependening on the zoom level, so precise layouting in an issue. My options are afaik</p>
  <ul>
  <li>displaying a JavaFX <code>Dialog</code> with <code>showAndWait</code> in a <code>Platform.runLater</code> and stop the Swing EDT with an invisible <code>JDialog</code>. That apparently causes deadlocks and is quite unelegant.</li>
  <li>put the JavaFX components in a <code>JFXPanel</code> and display it in a <code>JDialog</code>. That works in terms of modality, but I have no idea how to layout components in the <code>JFXPanel</code> since in a <code>GroupLayout</code> the panel simply grows infinitely (JavaFX <code>ScrollPane</code> don't have any effect).</li>
  </ul>
  <p>For example:</p>
  <pre><code>import javafx.application.Application;
  import javafx.scene.Scene;
  import javafx.scene.control.Button;
  import javafx.scene.control.ScrollPane;
  import javafx.scene.image.ImageView;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.layout.StackPane;
  import javafx.stage.Stage;
  
  public class NewMain1 extends Application {
      private final ImageView imageView;
  
      public NewMain1() {
          this.imageView = new ImageView(NewMain.class.getResource(&quot;/File_CC-BY-SA_3_icon_88x31.png&quot;).toString());
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  
      @Override
      public void start(Stage stage) throws Exception {
          BorderPane borderPane = new BorderPane();
          Button bottomButton = new Button(&quot;Some button&quot;);
          ScrollPane imageViewScrollPane = new ScrollPane(imageView);
          borderPane.setCenter(imageViewScrollPane);
          borderPane.setBottom(bottomButton);
          imageView.setSmooth(true);
          imageView.setFitHeight(400);
          StackPane  root  =  new  StackPane();
          root.getChildren().add(borderPane);
          stage.setScene(new Scene(root, 800, 600));
          stage.show();
      }
  }
  </code></pre>
  <p>shows a well working <code>ScrollPane</code> for the <code>ImageView</code> whereas in a <code>JFXPanel</code> in a <code>JDialog</code> the scrolling/layout doesn't work:</p>
  <pre><code>import java.awt.Dimension;
  import java.awt.EventQueue;
  import java.awt.HeadlessException;
  import javafx.application.Platform;
  import javafx.embed.swing.JFXPanel;
  import javafx.scene.Group;
  import javafx.scene.Scene;
  import javafx.scene.control.Button;
  import javafx.scene.control.ScrollPane;
  import javafx.scene.image.ImageView;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.paint.Color;
  import javax.swing.GroupLayout;
  import javax.swing.JButton;
  import javax.swing.JFrame;
  import javax.swing.WindowConstants;
  
  public class NewMain extends JFrame {
      private static final long serialVersionUID = 1L;
      private final JFXPanel mainPanel = new JFXPanel();
      private final ImageView imageView;
      private final JButton closeButton = new JButton(&quot;Close&quot;);
  
      public NewMain() throws HeadlessException {
          setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          setBounds(0, 0, 800, 600);
          setPreferredSize(new Dimension(800, 600));
          GroupLayout layout = new GroupLayout(this.getContentPane());
          this.getContentPane().setLayout(layout);
          layout.setAutoCreateContainerGaps(true);
          layout.setAutoCreateGaps(true);
          this.imageView = new ImageView(NewMain.class.getResource(&quot;/File_CC-BY-SA_3_icon_88x31.png&quot;).toString());
          Platform.runLater(() -&gt; {
              BorderPane borderPane = new BorderPane();
              Button bottomButton = new Button(&quot;Some button&quot;);
              ScrollPane imageViewScrollPane = new ScrollPane(imageView);
              borderPane.setCenter(imageViewScrollPane);
              borderPane.setBottom(bottomButton);
              imageView.setSmooth(true);
              imageView.setFitHeight(400);
              Group  root  =  new  Group();
              Scene  scene  =  new  Scene(root, Color.ALICEBLUE);
              root.getChildren().add(borderPane);
              mainPanel.setScene(scene);
          });
          closeButton.addActionListener((event) -&gt; {
              setVisible(false);
          });
          layout.setHorizontalGroup(layout.createParallelGroup()
                  .addComponent(mainPanel)
                  .addComponent(closeButton));
          layout.setVerticalGroup(layout.createSequentialGroup()
                  .addComponent(mainPanel)
                  .addComponent(closeButton));
          pack();
      }
  
      public static void main(String[] args) {
          EventQueue.invokeLater(() -&gt; {
              new NewMain().setVisible(true);
          });
      }
  }
  </code></pre>