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

Why is my JavaFX program using fxml getting the error "Caused by: java.lang.ClassNotFoundException: javafx.scene.control.VBox"?

提问人:Jacob Williams 提问时间:11/18/2023 更新时间:11/18/2023 访问量:42

问:

我有一个用 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;
}
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();
    }
}
<?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>

另外,这里是目录设置 来源 |-- 主 |-- 爪哇 | |-- 齿轮厂 | |-- App.java | |-- 资源 |-- 齿轮厂 |-- 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();
    }
}

我从一个包含更多代码的大型 gui 设计开始,但没有奏效,所以我尝试的是使代码尽可能小,最终得到了之前所说的简单程序。我预计在某个时候,我会占用一行它不喜欢的代码,然后系统地将其添加回去,直到我发现问题所在。

java javafx fxml

评论


答:

5赞 James_D 11/18/2023 #1

JavaFX 布局类(如 、 和 等)位于包中(而不是包中)。HBoxVBoxBorderPanejavafx.scene.layoutjavafx.scene.control

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

取代

<?import javafx.scene.control.HBox ?>

<?import javafx.scene.layout.HBox ?>

在 FXML 文件中。