I have created a new control by extending an existing one, and I would like to use this new control in my JavaFX scenes. I would like to be able to edit my scenes using Scene Builder, but after adding the new control to the FXML file, I am encountering a ClassNotFoundException
when opening Scene Builder.
For example, here is a class I made which extends TextField
:
RegexLimitingTextField.java
public class RegexLimitingTextField extends TextField {
private String regexLimiter = ".*";
public void setRegexLimiter(String regex) {
this.regexLimiter = regex;
}
@Override
public void replaceText(int start, int end, String text) {
if (text.matches(regexLimiter))
super.replaceText(start, end, text);
}
@Override
public void replaceSelection(String replacement) {
if (replacement.matches(regexLimiter))
super.replaceSelection(replacement);
}
}
After adding this control to my FXML file...
sample.fxml
<?import javafx.scene.layout.GridPane?>
<?import sample.RegexLimitingTextField?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<RegexLimitingTextField fx:id="textField" text="Test" />
</GridPane>
... I get this error when loading Scene Builder 2.0:
Caused by: java.lang.ClassNotFoundException: sample.RegexLimitingTextField
at java.lang.ClassLoader.findClass(ClassLoader.java:530)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at javafx.fxml.FXMLLoader.loadTypeForPackage(FXMLLoader.java:2920)
at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2909)
at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2850)
... 23 more
Why can't Scene Builder find my new control? What do I need to do in order for it to find and be able to use my new control?
Here are the other files if needed:
Main.java
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
}
Controller.java
public class Controller implements Initializable {
public RegexLimitingTextField textField;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
textField.setRegexLimiter("\\w*");
}
}
If anyone is still having troubles with SceneBuilder not loading their custom components, simply passing on a ClassLoader solved the issue for me.
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("CustomComponent.fxml"));
loader.setRoot(this);
loader.setController(this);
loader.setClassLoader(getClass().getClassLoader());
loader.load();
} catch (IOException e ){
throw new RuntimeException(e);
}
Credit goes to the miracle worker, thatjavaguy.
So ... after a lot of struggle I think I found the fix for this. The problem is so stupid that you won't believe.
This solution is only for thowse who allready tried everything, and did everything correctly, like:
So, it seems that you get ClassNotFoundException in Scene Builder also, if the custom component (.fxml and it's java controller) are in a package which is named starting with uppercase letter. It seems that all package names down to your custom component MUST start with lowercase letter. To be sure...just use lowercase to name all the packages. Another thing I noticed is that also the class name of the controller, MUST start with uppercase letter.
I also have had a lot of fun with a custom component extending TextField
and causing Scene Builder to freeze when opening.
The jar
file I added to Scene Builder only contained this one class. But my custom component has a reference to the controller — and that's the point. When I export both classes to the jar
, then everything is fine.
So if you are in a similar situation and looking for an answer, look closely at the dependencies. The world without Scene Builder is not the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With