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
Dialog
with showAndWait
in a Platform.runLater
and stop the Swing EDT with an invisible JDialog
. That apparently causes deadlocks and is quite unelegant.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.