简体   繁体   中英

How to provide JavaFX components in a dialog in a Swing application?

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 ImageView s for scanned images which can get quite big dependening on the zoom level, so precise layouting in an issue. My options are afaik

  • displaying a JavaFX Dialog with showAndWait in a Platform.runLater and stop the Swing EDT with an invisible JDialog . That apparently causes deadlocks and is quite unelegant.
  • put the JavaFX components in a JFXPanel and display it in a JDialog . That works in terms of modality, but I have no idea how to layout components in the JFXPanel since in a GroupLayout the panel simply grows infinitely (JavaFX ScrollPane don't have any effect).

For example:

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("/File_CC-BY-SA_3_icon_88x31.png").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("Some button");
        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();
    }
}

shows a well working ScrollPane for the ImageView whereas in a JFXPanel in a JDialog the scrolling/layout doesn't work:

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("Close");

    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("/File_CC-BY-SA_3_icon_88x31.png").toString());
        Platform.runLater(() -> {
            BorderPane borderPane = new BorderPane();
            Button bottomButton = new Button("Some button");
            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) -> {
            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(() -> {
            new NewMain().setVisible(true);
        });
    }
}

Don't make the root of the Scene a Group , Groups are not resizable.

Just remove the group and use a resizable layout for the scene root (you already have a resizable layout in your sample code, it's the BorderPane, so you can just use that).

Instead of:

Group  root  =  new  Group();
Scene  scene  =  new  Scene(root, Color.ALICEBLUE);
root.getChildren().add(borderPane);

Write:

Scene  scene  =  new  Scene(borderPane, Color.ALICEBLUE);

ScrollPane inside a JavaFX scene inside a JFXPanel inside a Swing JFrame.

快照

Note, that in your pure JavaFX NewMain1 application, you use are already using a resizable pane as a root (a StackPane), so that is the reason for the discrepancy that you observed between the pure JavaFX version and the Swing embedded version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM