简体   繁体   English

使用 Java Swing 和集成的 JavaFX 通过 Maven 创建可运行的 .jar - 实例化 JFXPanel 时应用程序崩溃

[英]Creating a runnable .jar with Maven using Java Swing and integrated JavaFX - App crashes when JFXPanel is being instantiated

I want to create runnable .jar-file with Maven.我想用 Maven 创建可运行的 .jar 文件。 The following code shows the main class (App.java), the class where the JFXPanel gets instantiated (ServiceToolEnty.java) and the pom.xml file.以下代码显示了主类 (App.java)、实例化 JFXPanel 的类 (ServiceToolEnty.java) 和 pom.xml 文件。

I create a simple JFrame with a button inside (Java Swing site).我创建了一个简单的 JFrame,里面有一个按钮(Java Swing 站点)。 Once the button has been clicked the JFXPanel should open the JavaFX thread to run javaFX code.单击按钮后,JFXPanel 应打开 JavaFX 线程以运行 javaFX 代码。

When I run the application in eclipse IDE everything works fine.当我在 Eclipse IDE 中运行应用程序时,一切正常。 After I created the .jar file with Maven and I try to run it via terminal (java -jar test-0.0.1-SNAPSHOT.jar), the following error message shows up:在我使用 Maven 创建 .jar 文件并尝试通过终端(java -jar test-0.0.1-SNAPSHOT.jar)运行它后,出现以下错误消息:

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: javafx/embed/swing/JFXPanel
    at com.carrier.ccr.test.App$1.actionPerformed(App.java:31)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6626)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389)
    at java.desktop/java.awt.Component.processEvent(Component.java:6391)
    at java.desktop/java.awt.Container.processEvent(Container.java:2266)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:746)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:744)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.ClassNotFoundException: javafx.embed.swing.JFXPanel
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 36 more

App.java:应用程序.java:


import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public class App extends JFrame{
 
    public App(){
        setSize(500, 180);
        setVisible(true);
        setLayout(null);
        setLocation(100, 100);

        //Button opens the ServiceTool interface
        JButton masterModeServiceTool = new JButton("Click here");
        masterModeServiceTool.setSize(280, 20);
        masterModeServiceTool.setFont(new Font("Arial",Font.PLAIN,15));
        add(masterModeServiceTool);
        masterModeServiceTool.setVisible(true);
        masterModeServiceTool.setLocation(10, 100);
        masterModeServiceTool.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                try {
                    ServiceToolEntry maServ=new ServiceToolEntry();
                    maServ.main();
                    setVisible(false);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

    }


    public static void main(String[] args) {
        App mv =new App();
        mv.addWindowListener(new WindowAdapter()
        {
            public void windowClosing (WindowEvent e) {
                System.exit (0);
            }
        });
    }
}

ServiceToolEnty.java (where the fx app is starting): ServiceToolEnty.java(fx 应用程序启动的地方):


import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class ServiceToolEntry {
    private static void initAndShowGUI() {
        // This method is invoked on the EDT thread
        JFrame frame = new JFrame("Click here");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setSize(1000, 700);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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


    private static Scene getScene() {
        Group  root  =  new  Group();
        Scene  scene  =  new  Scene(root, Color.ALICEBLUE);
        Text  text  =  new  Text();

        text.setX(40);
        text.setY(100);
        text.setFont(new Font(25));
        text.setText("Finally it's working");
        root.getChildren().add(text);

        return (scene);
    }


    private static void initFX(JFXPanel fxPanel) {
        Scene scene = getScene();
        fxPanel.setScene(scene);
    }


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

pom.xml file: pom.xml 文件:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.carrier.ccr</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>test</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
            <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>13</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>13</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>18-ea+5</version>
        </dependency>
        
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
            <plugin> 
    
               <!-- Building an executable jar -->
    
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-jar-plugin</artifactId>
               <version>3.1.0</version>
               <configuration>
                 <archive>
                   <manifest>
    
                   <!-- give full qualified name of your main class-->
                   <addClasspath>true</addClasspath>
                     <mainClass>com.carrier.ccr.test.App</mainClass>
    
                   </manifest>
                 </archive>
               </configuration>
            </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
        
        
      </plugins>
    </pluginManagement>
  </build>
</project>

You have numerous issues with your code and packaging.您的代码和包装有很多问题。 I can't really explain them all here now.我现在无法在这里解释所有这些。 But I present some alternatives you could try to work with if you wish.但是,如果您愿意,我提出了一些您可以尝试使用的替代方案。

I'll also add the usual caveat: don't mix JavaFX and Swing unless you really have to.我还将添加通常的警告:除非您真的必须,否则不要混合使用 JavaFX 和 Swing。

Packaging Alternatives包装替代品

Ordered from the least to most self-contained options (not most to least desirable):从最少到最独立的选项(不是最理想到最不理想)排序:

  1. Thin jar without JavaFX dependencies没有JavaFX 依赖项的薄 jar

    • requires mandating that the application run on a JDK or Java runtime which includes pre-bundled JavaFX modules.要求强制应用程序在包含预捆绑 JavaFX 模块的 JDK 或 Java 运行时上运行。 For example, from the distributors mentioned below.例如,来自下面提到的分销商。 If used, ensure you select their distributions of the JDK which include JavaFX :如果使用,请确保选择他们的 JDK 发行版,其中包括 JavaFX

    • You don't need to put JavaFX dependencies in your Maven project as they are already available in the underlying platform.您不需要将 JavaFX 依赖项放在您的 Maven 项目中,因为它们已经在底层平台中可用。

    • If it is a simple application, without any other dependencies than the standard JDK and JavaFX, then you can package the application as an executable jar with no dependencies.如果是一个简单的应用程序,除了标准的JDK和JavaFX之外没有任何其他依赖项,那么您可以将应用程序打包为一个没有依赖项的可执行jar。

  2. Shaded "fat" jar (or zip) without JavaFX dependencies没有JavaFX 依赖项的阴影的“胖”jar(或 zip)

    • If you have non-javafx dependencies, you can use the info in the solutions for "fat" jar with JavaFX dependencies or zip without JRE.如果您有非 javafx 依赖项,您可以使用“fat”jar 与 JavaFX 依赖项或不带 JRE 的 zip 的解决方案中的信息。
      • Don't place the JavaFX dependencies in your maven project dependency list.不要将 JavaFX 依赖项放在您的 Maven 项目依赖项列表中。
      • Ensure that you and your users are always using a JDK or java runtime which includes JavaFX.确保您和您的用户始终使用包含 JavaFX 的 JDK 或 Java 运行时。
  3. Shaded "fat" jar (jar) with JavaFX dependencies带有JavaFX 依赖项的阴影“胖”jar (jar)

  4. Zip without JRE (zip, tar, tar.gz, tar.bz2)不带 JRE 的 Zip(zip、tar、tar.gz、tar.bz2)

  5. Zip with JRE (zip, tar, tar.gz, tar.bz2)使用 JRE 压缩(zip、tar、tar.gz、tar.bz2)

    • use jlink to create a runtime image directory.使用jlink创建运行时映像目录。
    • create a zip of the runtime image with an assembly .使用程序集创建运行时映像的 zip。
  6. Windows exe (exe)视窗exe(exe)

  7. Native installer (msi, dmg, app, rpm, deb)本机安装程序(msi、dmg、app、rpm、deb)

In terms of ease of use for users, I'd recommend the later ones which bundle a working Java runtime: either a Native installer, Zip with JRE, or Windows exe.就用户的易用性而言,我推荐后者捆绑了可运行的 Java 运行时:本机安装程序、带有 JRE 的 Zip 或 Windows exe。

I think the solutions which require the user to have a valid JRE installed are less desirable for many applications.我认为要求用户安装有效 JRE 的解决方案对于许多应用程序来说不太理想。

  • With no bundled JRE, the difficult work of ensuring the right JRE is present and properly configured is shifted to every user rather than the developer.由于没有捆绑的 JRE,确保存在正确的 JRE 并正确配置的艰巨工作转移到每个用户而不是开发人员。
  • The Maven shade "fat" jar option which includes JavaFX dependencies isn't one supported by the JavaFX development team. JavaFX 开发团队不支持包含 JavaFX 依赖项的 Maven 阴影“胖”jar 选项。

For Maven Users对于 Maven 用户

  • jlink can be invoked from the OpenJFX JavaFX Maven plugin . jlink 可以从OpenJFX JavaFX Maven 插件调用。
  • jpackage can be invoked from the akman jpackage maven plugin . jpackage 可以从akman jpackage maven plugin调用。
    • jpackage can also create images, the same as jlink. jpackage也可以创建图片,和jlink一样。
    • If creating native installers, I recommend having jpackage handle both the linking and packaging (jpackage will warn you if you do not do this).如果创建本机安装程序,我建议让 jpackage 处理链接和打包(如果你不这样做,jpackage 会警告你)。
    • On some options for windows apps, I found that jlink did not place the required icons in the right place by default, resulting in weird and hard to track down issues that did not occur when jpackage did the linking.在 windows 应用程序的某些选项上,我发现 jlink 默认没有将所需的图标放置在正确的位置,导致奇怪且难以追踪 jpackage 进行链接时没有发生的问题

Zip without JRE Option不带 JRE 选项的 Zip

The rest of this answer focuses purely on the Zip without JRE option.这个答案的其余部分完全集中在没有 JRE 选项的 Zip 上。

See the readme at the end of the answer which describes what this is and how to use it.请参阅答案末尾的自述文件,其中描述了这是什么以及如何使用它。 If it is not what you are looking for, just ignore it and try to solve your issues another way.如果这不是您要查找的内容,请忽略它并尝试以另一种方式解决您的问题。

The solution is not an executable jar.解决方案不是一个可执行的 jar。 Instead, it is a set of java modules packaged in jar format, executed via a launcher script and assembled into a compressed archive file.相反,它是一组以 jar 格式打包的 java 模块,通过启动程序脚本执行并组装成压缩存档文件。

  • It requires that JRE 17+ be installed on the target machine.它要求在目标机器上安装 JRE 17+。

  • The application is only packaged for executing on an Intel Mac (at least when it has been built on an Intel Mac).该应用程序仅打包用于在 Intel Mac 上执行(至少当它已构建在 Intel Mac 上时)。

    • Packaging for other platforms is possible, but is outside the scope of what I am discussing here.其他平台的打包是可能的,但这超出了我在这里讨论的范围。

Swing<->JavaFX integration Swing<->JavaFX 集成

The solution is for a Swing+JavaFX application.该解决方案适用于 Swing+JavaFX 应用程序。 Normally I wouldn't recommend such a configuration, however it is presented here because that is what the question asked about.通常我不会推荐这样的配置,但是在这里提出它是因为这就是问题所问的问题。 The Swing<->JavaFX integration code follows the structure and guidelines provided in Oracle's tutorial: Integrating JavaFX into Swing Applications . Swing<->JavaFX 集成代码遵循 Oracle 教程中提供的结构和准则: 将 JavaFX 集成到 Swing 应用程序中

If you don't have Swing in your application, remove the Swing application, the javafx.swing requirement in the module definition and the javafx-swing dependency from Maven, and reconfigure the launcher script to directly call the JavaFX HelloApplication and everything will work fine for a pure JavaFX application distribution without Swing.如果您的应用程序中没有 Swing,请从 Maven 中删除 Swing 应用程序、模块定义中的 javafx.swing 要求和 javafx-swing 依赖项,并重新配置启动程序脚本以直接调用 JavaFX HelloApplication,一切都会正常进行对于没有 Swing 的纯 JavaFX 应用程序分发。

File tree文件树

$ tree
├── pom.xml
├── readme.md
└── src
    ├── assembly
    │   └── bin.xml
    └── main
        ├── command
        │   └── swingfx.sh
        ├── java
        │   ├── com
        │   │   └── example
        │   │       └── swingfx
        │   │           ├── HelloApplication.java
        │   │           ├── HelloController.java
        │   │           └── SwingApp.java
        │   └── module-info.java
        └── resources
            └── com
                └── example
                    └── swingfx
                        └── hello-view.fxml

I skipped providing the JavaFX FXML and Controller code because they aren't relevant to the solution, they are just formed from standard code that you can find in any basic FXML tutorial.我跳过提供 JavaFX FXML 和控制器代码,因为它们与解决方案无关,它们只是由您可以在任何基本 FXML 教程中找到的标准代码构成。

pom.xml pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>SwingFX</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>SwingFX</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javafx.version>17.0.1</javafx.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>${javafx.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <descriptors>
                        <descriptor>src/assembly/bin.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

module-info.java模块信息.java

module com.example.swingfx {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.swing;

    opens com.example.swingfx to javafx.fxml;
    exports com.example.swingfx;
}

SwingApp.java Swing应用程序

package com.example.swingfx;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;

import javax.swing.*;
import java.awt.*;

public class SwingApp {

    private static void initAndShowGUI() {
        JFrame frame = new JFrame("Swing Main App JFrame");
        frame.setSize(500, 180);
        frame.setVisible(true);
        frame.setLayout(null);
        frame.setLocation(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Button opens the ServiceTool interface
        JButton toolLauncher = new JButton("Launch JavaFX Tool");
        toolLauncher.setSize(280, 20);
        toolLauncher.setFont(new Font("Arial", Font.PLAIN, 15));
        toolLauncher.setVisible(true);
        toolLauncher.setLocation(10, 100);
        toolLauncher.addActionListener(e -> launchFXTool());
        frame.add(toolLauncher);
    }

    private static void launchFXTool() {
        try {
            // This method is invoked on the EDT thread
            // The method creates a new frame and JavaFX scene whenever it is invoked.
            // If preferred and only one instance is required, then cache the JFrame
            // on first launch, then show and focus the existing JFrame when the tool is relaunched.
            JFrame frame = new JFrame("Swing JFrame with JavaFX scene content");
            final JFXPanel fxPanel = new JFXPanel();
            frame.add(fxPanel);
            frame.setSize(300, 200);
            frame.setVisible(true);

            Platform.runLater(() -> {
                // This logic is invoked on the JavaFX thread
                try {
                    fxPanel.setScene(
                            HelloApplication.createScene()
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SwingApp::initAndShowGUI);
    }
}

HelloApplication.java你好应用程序

package com.example.swingfx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        stage.setTitle("Hello!");
        stage.setScene(createScene());
        stage.show();
    }

    public static Scene createScene() throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        return new Scene(fxmlLoader.load(), 320, 240);
    }

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

swingfx.sh swingfx.sh

#!/bin/sh
VM_OPTIONS=
DIR=`dirname $0`
MODULE_PATH=$DIR/../lib
MAIN_CLASS=com.example.swingfx/com.example.swingfx.SwingApp 
# if desired you could add a check to ensure a compatible java version is installed and print a friendly error message if not.
# launches a java app with the given vm options and module path, passing the arguments provided to this script to the app.
java $VM_OPTIONS -p $MODULE_PATH -m $MAIN_CLASS "$@"

bin.xml二进制文件

<assembly>
    <id>bin</id>
    <formats>
        <format>tar.gz</format>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <scope>runtime</scope>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>src/main/command</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>*.sh</include>
                <include>*.bat</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
    </fileSets>
</assembly>

readme.md自述文件

Example of a Swing application integrated with JavaFX.与 JavaFX 集成的 Swing 应用程序示例。 The application is built as a Java module application.该应用程序构建为 Java 模块应用程序。

Build Requirements构建要求

  • Java JDK 17+ Java JDK 17+
  • Maven 3.8+ Maven 3.8+

Execution Requirements执行要求

  • Java JRE 17+ Java JRE 17+
  • Mac OS X Intel Mac OS X 英特尔

Build Instructions构建说明

Build and package the application:构建和打包应用程序:

mvn package

The build will create the following file:构建将创建以下文件:

target/SwingFX-1.0-SNAPSHOT-bin.tar.gz

Execution instructions执行指令

  1. Extract the application binary from the archive.从存档中提取应用程序二进制文件。

     tar xzvf SwingFX-1.0-SNAPSHOT-bin.tar.gz
  2. Run the application:运行应用程序:

     SwingFX-1.0-SNAPSHOT/bin/swingfx.sh

Contents of the distribution分发内容

$ tar xvzf SwingFX-1.0-SNAPSHOT-bin.tar.gz 
x SwingFX-1.0-SNAPSHOT/bin/swingfx.sh
x SwingFX-1.0-SNAPSHOT/lib/javafx-controls-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-controls-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-graphics-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-graphics-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-base-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-base-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-fxml-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-fxml-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-swing-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-swing-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/SwingFX-1.0-SNAPSHOT.jar

Troubleshooting故障排除

If you see the following error, java is not installed and on the default path:如果您看到以下错误,则说明 java 未安装且位于默认路径:

-bash: java: command not found

If you see an error such as the following:如果您看到如下错误:

Caused by: java.lang.module.InvalidModuleDescriptorException: Unsupported major.minor version 61.0

Java is installed but it is not Java 17+, you need to upgrade the Java installation to a later version, you can check the current version using java -version Java已安装但不是Java 17+,您需要将Java安装升级到更高版本,您可以使用java -version检查当前版本

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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