I have a program that was created with java swing, but I hit a point where using it without much online help with issues I ran into so I am starting to learn JavaFX and using fxml for the gui, so I tried to create the main window in JavaFX code. With only code, I was able to make it appear how I wanted. I then decided to switch it to fxml, so I created the fxml file, added the code in my java file to load it, but when i ran the program, I keep getting the error "Caused by: java.lang.ClassNotFoundException: javafx.scene.control.VBox", or the same for HBox, depending on which I used. I tried figuring it out myself, also tried chatGpt, but but I couldn't find a solution. What confuses me is that when I first created the JavaFX project in VS Code, it used VBox in the fxml, but worked fine. I have copied all code that that used, just changed the fxml nodes. For context, here is the module file, my code, and the fxml file.
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>
Also, here is the directory setup src |-- main |-- java | |-- gearworks | |-- App.java | |-- resources |-- gearworks |-- BasicGui.fxml
This is just the simple version of the program I am trying to make, I just kept shrinking the design, hoping that at some point it would work and I would go from there, but it never did.
This was the original code that worked before trying to use fxml, minus the imports
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();
}
}
I started with a large gui design with more code, which didn't work, so what I tried was to make the code as small as possible, ending up the simple program said before. I expected that at some point, I would take a line of code that it didn't like, and then systematically adding it back until I found the issue.