尽管 JavaFX 应用程序中的 module-info.java 中存在“require”,但仍出现“找不到模块”错误

Anu*_*hal 5 java javafx

我正在开发用于屏幕录制的 JavaFX 项目。我需要录制整个屏幕。我使用依赖monte-screen-recorder

这是我的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.screenRecorder</groupId>
    <artifactId>ScreenRecorder</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>ScreenRecorder</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>5.9.2</junit.version>
    </properties>

    <dependencies>
        <!-- JavaCV dependencies -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.jcodec</groupId>
            <artifactId>jcodec-javase</artifactId>
            <version>0.2.3</version>
        </dependency>
        <!-- JavaFX dependencies -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>17.0.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.stephenc.monte/monte-screen-recorder -->
        <dependency>
            <groupId>com.github.stephenc.monte</groupId>
            <artifactId>monte-screen-recorder</artifactId>
            <version>0.7.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.kokorin.jaffree</groupId>
            <artifactId>jaffree</artifactId>
            <version>2023.09.10</version>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <!-- Maven Compiler Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>

            <!-- JavaFX Maven Plugin -->
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <executions>
                    <execution>
                        <id>default-cli</id>
                        <configuration>
                            <mainClass>
                                com.screenrecorder.screenrecorder.HelloApplication
                            </mainClass>
                            <launcher>app</launcher>
                            <jlinkZipName>app</jlinkZipName>
                            <jlinkImageName>app</jlinkImageName>
                            <noManPages>true</noManPages>
                            <stripDebug>true</stripDebug>
                            <noHeaderFiles>true</noHeaderFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
Run Code Online (Sandbox Code Playgroud)

这是我的应用程序代码:

package com.screenrecorder;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.monte.media.Format;
import org.monte.media.FormatKeys;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;

import java.awt.*;

import static org.monte.media.FormatKeys.MediaTypeKey;
import static org.monte.media.VideoFormatKeys.ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE;

public class ScreenRecorderApp extends Application {

    private ScreenRecorder screenRecorder;
    private boolean isRecording = false;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button startButton = new Button("Start Recording");
        startButton.setOnAction(event -> startRecording());

        Button stopButton = new Button("Stop Recording");
        stopButton.setOnAction(event -> stopRecording());

        VBox root = new VBox(10, startButton, stopButton);
        Scene scene = new Scene(root, 300, 200);

        primaryStage.setScene(scene);
        primaryStage.setTitle("Screen Recorder");
        primaryStage.show();
    }

    private void startRecording() {
        try {
            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
                    .getDefaultScreenDevice()
                    .getDefaultConfiguration();

            screenRecorder = new ScreenRecorder(gc, null, new Format(MediaTypeKey, FormatKeys.EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                    FormatKeys.FrameRateKey, Rational.valueOf(15)), new Format(MediaTypeKey, FormatKeys.EncodingKey, "black", FormatKeys.FrameRateKey, Rational.valueOf(30)),
                    null);
            screenRecorder.start();

            isRecording = true;
            System.out.println("Recording started...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void stopRecording() {
        if (isRecording && screenRecorder != null) {
            try {
                screenRecorder.stop();
                System.out.println("Recording stopped...");
            } catch (Exception e) {
                e.printStackTrace();
            }
            isRecording = false;
        }
    }

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

Run Code Online (Sandbox Code Playgroud)

这是我的module-info.java文件:

module com.screenrecorder {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.media;
    requires java.desktop;
    requires jcodec.javase;
    requires monte.screen.recorder;

    opens com.screenrecorder to javafx.fxml;
    exports com.screenrecorder;

}
Run Code Online (Sandbox Code Playgroud)

当我运行我的应用程序时,我收到此错误:

java: module not found: monte.screen.recorder
Run Code Online (Sandbox Code Playgroud)

我不知道为什么我会遇到这个错误。我的代码需要改变什么?

我正在尝试一些更改,但仍然面临同样的错误。

尝试使用不同的库,但我没有找到任何一个。

jew*_*sea 3

为什么不能将屏幕录像机 jar 作为模块使用

不能将屏幕记录器 jar 用作模块的原因是该 jar 包含不在任何命名的 Java 包中的类

即使您需要有效的模块名称,也可能有其他原因导致 jar 无法作为模块运行(例如包冲突),因为 jar 从未被创建为用作模块。它可能仍然有效(也可能无效)。

要测试其中一些方面,您可以使用该jar工具从 jar 中获取模块信息:

jar --describe-module --file ~/.m2/repository/com/github/stephenc/monte/monte-screen-recorder/0.7.7.0/monte-screen-recorder-0.7.7.0.jar
Run Code Online (Sandbox Code Playgroud)

您将收到类似于以下内容的输出:

Unable to derive module descriptor for: ~/.m2/repository/com/github/stephenc/monte/monte-screen-recorder/0.7.7.0/monte-screen-recorder-0.7.7.0.jar
ScreenRecorder.class found in top-level directory (unnamed package not allowed in module)
Run Code Online (Sandbox Code Playgroud)

确定屏幕录像机依赖项的正确模块名称

了解自动模块如何工作。正如其他人在评论中指出的那样,请为模块使用正确的名称。

由于 jar 没有module-info.javaAutomatic-Module-Name,因此使用的名称将为monte.screen.recorder,基于注释中 VGR 链接的ModuleFinder 文档中的 jar 名称到模块名称映射规则。

这是因为依赖项中的artifactId 是monte-screen-recorder,这表明jar 名称是monte-screen-recorder.jar

您可以在使用时需要该 jar 作为模块module-info.java

requires monte.screen.recorder;
Run Code Online (Sandbox Code Playgroud)

但这是您已经拥有的,因此并不是使用不正确的模块名称导致您的问题。

建议:使您的项目成为非模块化的

您还有其他未用作模块的依赖项(例如,javacvjaffree)。

当您有很多像这样的非模块化依赖项时,我不建议将您的应用程序模块化。您在使用模块系统时会经历很多痛苦,却很少意识到它的好处。

相反,在模块路径之外运行 JavaFX 和核心 JDK(因为这就是它们的工作方式),但使您的应用程序成为非模块化的(删除 )module-info.javaopenjfx.io 上的入门说明包含有关使用 JavaFX 技术开发非模块化应用程序的各种方法的信息。

不使用模块意味着您无法使用jlink. 但是,jlink无论如何不适用于自动模块,因此jlink无论您的应用程序是否是模块化的,您在 pom.xml 中的配置都无法工作。

  • 查看您的第一条评论和第二条评论中的错误消息不同。您不能指望对您在评论中添加的不同内容提供帮助,请不要在那里询问。我已经在回答中解释过,您不能使用包含屏幕录像机的 jar 作为模块,以及为什么会这样。 (2认同)