如何将 Swing JPanel 嵌入到 JavaFX 框架中?

How do you embed a Swing JPanel into a JavaFX frame?

来自Integrating JavaFX 2.0 with Swing and SWT there is a code that allows you to embed a JFXPanel inside a Swing JFrame. I was wondering is there a reverse of that where a JPanel is embedded inside an Application or Stage which is the equivalent of JFrame as noted in

/**
 * Simple class demonstrating interoperability between Swing and JavaFX. This
 * class is adapted from the example provided in the Javadoc documentation for
 * {@code javafx.embed.swing.JFXPanel}.
 */
public class SwingJavaFxInteroperabilityDemo
{
   private static void initAndShowGUI()
   {
      // This method is invoked on Swing thread
      final JFrame frame = new JFrame("JavaFX / Swing Integrated");
      final JFXPanel fxPanel = new JFXPanel();
      frame.add(fxPanel);
      frame.setVisible(true);

      Platform.runLater(new Runnable()
      {
         @Override
         public void run()
         {
            initFX(fxPanel);
         }
      });
   }

   private static void initFX(JFXPanel fxPanel)
   {
      // This method is invoked on JavaFX thread
      final Scene scene = TextIntegrationSceneCreator.createTextScene();
      fxPanel.setScene(scene);
   }

   public static void main(String[] arguments)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         @Override
         public void run()
         {
            initAndShowGUI();
         }
      });
   }   
}

您可以使用 SwingNode 将 swing 内容放入 JavaFX 节点。

示例应用程序

之前链接的 SwingNode 文档中有一个示例应用程序:

import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import javax.swing.*;

public class SwingFx extends Application {

    @Override
    public void start(Stage stage) {
        final SwingNode swingNode = new SwingNode();
        createAndSetSwingContent(swingNode);

        StackPane pane = new StackPane();
        pane.getChildren().add(swingNode);

        stage.setScene(new Scene(pane, 100, 50));
        stage.show();
    }

    private void createAndSetSwingContent(
        final SwingNode swingNode
    ) {
        SwingUtilities.invokeLater(() -> 
                swingNode.setContent(
                        new JButton("Click me!")
                )
        );
    }

    public static void main(String[] args) {
        launch(args);
    }
}

依赖和模块管理

如果您使用 Maven 或 Gradle 作为您的 JavaFX 依赖项,您可以使用以下方法导入 JavaFX/Swing 集成库:

<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-swing</artifactId>
    <version>16</version>
</dependency>

如果您正在使用 Jigsaw 功能编写模块化应用程序,将以下内容放入 module-info.java 文件将使 JavaFX swing 集成模块对您的应用程序可见:

requires javafx.swing;

在 JavaFX 教程中嵌入 Swing

Oracle 为在 JavaFX:

中嵌入 Swing 内容提供了很好的教程

本教程是为 Java 8 编写的,但仍然适用。本教程涵盖线程管理和事件处理等主题,我建议任何尝试集成 JavaFX 和 Swing 的人在尝试集成之前充分理解这些主题,否则可能会出现糟糕和不可预测的事情。

一般来说,我建议不要混合使用 JavaFX 和 Swing 代码,除非这对于您的应用程序是绝对必要的。

Canvas 集成和重量级 Swing 组件

请注意,来自 SwingNode 文档:

The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise, SwingNode may fail to paint it.

重量级组件的一个例子是Canvas。如果您想在 JavaFX 中使用 awt canvas,请参阅:

具体来说,考虑使用 FXGraphics2D 库:

FXGraphics2D is an implementation of Java2D's Graphics2D API that targets a JavaFX canvas.


Maven doesn't know a javafx.embed.swing. Any idea where to find it?

正确配置的 Maven 设置不应该是这种情况。

所有 JavaFX 框架模块都在 central maven repository.

中央 Maven 存储库在标准 Maven 安装中默认启用。

javafx-swing 的 Maven 坐标已经在这个答案中(在标题为“依赖和模块管理”的部分下)。

更新依赖版本以匹配您正在使用的 JavaFX 版本。

依赖项的最新稳定版本是 18.0.1 今天,因此要使用它,请确保您依赖的 all javafx 组件使用该版本作为它们的 Java外汇依赖。

或者,您可以

但是,我建议使用 Maven 或 Gradle 构建工具的依赖项,而不是依赖手动下载的模块或 JavaFX SDK。