为什么我使用 fxml 的 JavaFX 程序出现错误“Caused by: java.lang.ClassNotFoundException: javafx.scene.control.VBox”?

0 java javafx fxml

我有一个用 java swing 创建的程序,但是我遇到了一个问题,在没有太多在线帮助的情况下使用它来解决我遇到的问题,所以我开始学习 JavaFX 并使用 fxml 作为 gui,所以我尝试创建主窗口在 JavaFX 代码中。只用代码,我就能让它看起来像我想要的那样。然后我决定将其切换到 fxml,因此我创建了 fxml 文件,在我的 java 文件中添加了代码来加载它,但是当我运行该程序时,我不断收到错误“Caused by: java.lang.ClassNotFoundException: javafx .scene.control.VBox”,或与 HBox 相同,具体取决于我使用的。我尝试自己解决这个问题,也尝试过chatGpt,但我找不到解决方案。让我困惑的是,当我第一次在 VS Code 中创建 JavaFX 项目时,它在 fxml 中使用了 VBox,但工作正常。我已经复制了使用的所有代码,只是更改了 fxml 节点。对于上下文,这里是模块文件、我的代码和 fxml 文件。

module gearworks {
    requires javafx.controls;
    requires javafx.fxml;

    opens gearworks to javafx.fxml;
    exports gearworks;
}
Run Code Online (Sandbox Code Playgroud)
package gearworks;

import java.io.IOException;

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

/**
 * JavaFX App
 */
public class App extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("/gearworks/BaseGui.fxml"));
        try {
            root = loader.load();
            System.out.println((root == null) + " root is null");
            if (root == null) {
                throw new IOException("FXML root is null");
                
            }
        } catch (IOException e) {
            
            e.printStackTrace();
        }
        Scene scene = new Scene(root, 1300, 600);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Test Gui");
        primaryStage.setOnCloseRequest(e -> primaryStage.close());
        primaryStage.show();
    }
}
Run Code Online (Sandbox Code Playgroud)
<?fxml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>

<BorderPane xmlns="http://javafx.com/javafx/8.0.171"
    xmlns:fx="http://javafx.com/fxml/1"
    fx:controller="gearworks.App">
    <top>
        <HBox>
            <Children>
                <Button text="button 1" />
                <Label text="label 1" />
                <Button text="button 2" />
            </Children>
        </HBox>
    </top>
</BorderPane>

Run Code Online (Sandbox Code Playgroud)

另外,这里是目录设置 src |-- main |-- java | |-- 齿轮厂 | |-- App.java | |-- 资源 |-- gearworks |-- BasicGui.fxml

这只是我正在尝试制作的程序的简单版本,我只是不断缩小设计,希望在某个时候它会起作用并且我会从那里开始,但它从来没有这样做过。

这是在尝试使用 fxml 之前有效的原始代码,减去导入

public class App extends Application {

    

    private BorderPane root;
    private HBox openFilePanel, saveFilePanel, dataManipulationPanel, jobSelectionPanel, displayPanel, bottomPanel,
            jobFilterPanel;
    private VBox bottom;
    private Label openFilePathLabel, saveFilePathLabel, currentJob;
    private Button chooseOpenFile, updateBidders, chooseSaveFolder, saveExcel, filterJobs, addPricing, previousJob,
            nextJob;

    private final Font TITLE_FONT = Font.font("Monospaced", FontWeight.BOLD, 50);
    private final Font FONT = Font.font("Monospaced", FontWeight.NORMAL, 16);

    private final String css = this.getClass().getResource("Element_Styles.css").toExternalForm();
    // Dark Theme Colors
    private final Color PRIMARY_FONT_COLOR = Color.rgb(0, 179, 189);
    private final Color SECONDARY_FONT_COLOR = Color.rgb(55, 136, 186);
    private final Color TERTIARY_FONT_COLOR = Color.rgb(192, 155, 82);
    private final Color QUATERNARY_FONT_COLOR = Color.rgb(61, 86, 123);

    private final Color PRIMARY_BACKGROUND = Color.rgb(13, 21, 33);
    private final Color SECONDARY_BACKGROUND = Color.rgb(16, 26, 41);

    private final Color TITLE_FONT_COLOR = TERTIARY_FONT_COLOR;

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

    @Override
    public void start(Stage primaryStage) {

        root = new BorderPane();

        openFilePanel = new HBox();
        openFilePanel.setPadding(new Insets(10));
        openFilePanel.setAlignment(Pos.CENTER_LEFT);

        openFilePathLabel = new Label("File Path:  ");
        openFilePathLabel.setPadding(new Insets(10));
        openFilePathLabel.setFont(FONT);
        openFilePathLabel.setTextFill(QUATERNARY_FONT_COLOR);

        chooseOpenFile = new Button("Open Bidding File...");

        updateBidders = new Button("Add Update Bidders");
        updateBidders.setDisable(true);

        // Add spacer to push the label to the left
        Region ofpSpacer = new Region();
        HBox.setHgrow(ofpSpacer, Priority.ALWAYS);

        openFilePanel.getChildren().addAll(chooseOpenFile, openFilePathLabel, ofpSpacer, updateBidders);

        saveFilePanel = new HBox();
        saveFilePanel.setPadding(new Insets(10));
        saveFilePanel.setAlignment(Pos.CENTER_LEFT);

        saveFilePathLabel = new Label("Directory Path:  ");
        saveFilePathLabel.setPadding(new Insets(10));
        saveFilePathLabel.setFont(FONT);
        saveFilePathLabel.setTextFill(QUATERNARY_FONT_COLOR);

        chooseSaveFolder = new Button("Choose a Save Folder...");
        saveExcel = new Button("Export Excel File");

        // Add spacer to push the label to the left
        Region sfpSpacer = new Region();
        HBox.setHgrow(sfpSpacer, Priority.ALWAYS);

        saveFilePanel.getChildren().addAll(chooseSaveFolder, saveFilePathLabel, sfpSpacer, saveExcel);

        dataManipulationPanel = new HBox();
        dataManipulationPanel.setPadding(new Insets(10, 10, 0, 10));

        filterJobs = new Button("Confirm Selected Jobs");
        addPricing = new Button("Add Pricing to Jobs");
        jobFilterPanel = new HBox();
        jobFilterPanel.setSpacing(10);
        jobFilterPanel.getChildren().addAll(filterJobs, addPricing);

        previousJob = new Button("<< Previous Job");
        currentJob = new Label("(00/00)");
        currentJob.setFont(FONT);
        currentJob.setTextFill(QUATERNARY_FONT_COLOR);
        nextJob = new Button("Next Job >>");
        jobSelectionPanel = new HBox();
        jobSelectionPanel.setSpacing(10);
        jobSelectionPanel.setAlignment(Pos.CENTER);
        HBox.setHgrow(jobSelectionPanel, Priority.ALWAYS); // Expand to fill available space
        jobSelectionPanel.getChildren().addAll(previousJob, currentJob, nextJob);

        dataManipulationPanel.getChildren().addAll(jobFilterPanel, jobSelectionPanel);

        bottom = new VBox();
        bottom.getChildren().addAll(dataManipulationPanel, saveFilePanel);

        primaryStage.setTitle("Test Gui");

        root.setTop(openFilePanel);

        Label titleLabel = new Label("BIDDING PROGRAM");
        titleLabel.setFont(TITLE_FONT);
        titleLabel.setTextFill(TITLE_FONT_COLOR);

        Label descriptionLabel = new Label("Click \"Open Bidding File\" To Get Started");
        descriptionLabel.setFont(FONT);
        descriptionLabel.setTextFill(SECONDARY_FONT_COLOR);

        VBox displayBox = new VBox(titleLabel, descriptionLabel);
        displayBox.setAlignment(Pos.CENTER);
        displayBox.setSpacing(10);
        displayBox.setBackground(new Background(new BackgroundFill(SECONDARY_BACKGROUND, null, null)));

        root.setCenter(displayBox);

        root.setBottom(bottom);
        Scene scene = new Scene(root, 1300, 600);
        primaryStage.setScene(scene);

        scene.getStylesheets().add(css);
        primaryStage.setOnCloseRequest(e -> primaryStage.close());
        primaryStage.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

我开始时使用了更多代码的大型 GUI 设计,但这是行不通的,所以我尝试的是使代码尽可能小,最终得到了前面所说的简单程序。我预计在某个时候,我会采用一行它不喜欢的代码,然后系统地将其添加回来,直到找到问题为止。

Jam*_*s_D 5

JavaFX 布局类,如HBoxVBox、 和BorderPane等都在javafx.scene.layout包中(不是javafx.scene.control包)。

因此,当FXMLLoader遇到时javafx.scene.control.HBox它会抛出一个ClassNotFoundException,因为没有这样的类。

代替

<?import javafx.scene.control.HBox ?>
Run Code Online (Sandbox Code Playgroud)

<?import javafx.scene.layout.HBox ?>
Run Code Online (Sandbox Code Playgroud)

在 FXML 文件中。