Java 场景生成器中的自定义控件ClassNotFoundException

Java 场景生成器中的自定义控件ClassNotFoundException,java,javafx,classnotfoundexception,scenebuilder,Java,Javafx,Classnotfoundexception,Scenebuilder,我通过扩展现有控件创建了一个新控件,我希望在JavaFX场景中使用这个新控件。我希望能够使用Scene Builder编辑场景,但在将新控件添加到FXML文件后,在打开Scene Builder时遇到ClassNotFoundException 例如,我创建了一个类,它扩展了TextField: RegexLimitingTextField.java public class RegexLimitingTextField extends TextField { private Stri

我通过扩展现有控件创建了一个新控件,我希望在JavaFX场景中使用这个新控件。我希望能够使用Scene Builder编辑场景,但在将新控件添加到FXML文件后,在打开Scene Builder时遇到
ClassNotFoundException

例如,我创建了一个类,它扩展了
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);
    }
}
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();
    }
}
public class Controller implements Initializable {
    public RegexLimitingTextField textField;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        textField.setRegexLimiter("\\w*");
    }
}
将此控件添加到我的FXML文件后

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>
为什么场景生成器找不到我的新控件?我需要做什么才能让它找到并能够使用我的新控件

以下是其他文件(如果需要):

Main.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);
    }
}
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();
    }
}
public class Controller implements Initializable {
    public RegexLimitingTextField textField;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        textField.setRegexLimiter("\\w*");
    }
}
Controller.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);
    }
}
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();
    }
}
public class Controller implements Initializable {
    public RegexLimitingTextField textField;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        textField.setRegexLimiter("\\w*");
    }
}

如果任何人在SceneBuilder没有加载他们的自定义组件方面仍然有问题,那么只需传递一个类加载器就可以为我解决这个问题

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);
}

归功于。

所以。。。经过一番努力,我想我找到了解决办法。这个问题太愚蠢了,你不会相信的

此解决方案仅适用于所有准备就绪的人,他们尝试了所有方法,并且所有方法都正确,例如:

  • 正如Brad Turek所说,在为自定义组件创建控制器时传递类加载器
  • 对.fxml使用fx:root构造

因此,如果自定义组件(.fxml及其java控制器)位于名为以大写字母开头的包中,那么在场景生成器中似乎也会出现ClassNotFoundException。似乎所有的包名直到您的自定义组件都必须以小写字母开头。当然…只需使用小写字母来命名所有包。我注意到的另一件事是,控制器的类名也必须以大写字母开头。

我还从扩展
TextField
并使场景生成器在打开时冻结的自定义组件中获得了很多乐趣

我添加到场景生成器中的
jar
文件只包含这一类。但是我的自定义组件有一个对控制器的引用,这就是重点。当我将这两个类导出到
jar
时,一切都很好


因此,如果您处于类似的情况下,并且正在寻找答案,请仔细查看依赖关系。没有场景生成器的世界是不一样的。

可能是@James_D的复制品,很有效,谢谢。不过我有点生气。为什么要删除
scenebuilder类路径元素
标记?这似乎意味着每次我对类进行更改时,我都必须重新构建jar并重新导入它。“没有比这更简单的方法了吗?听到这个消息我很难过,”Serhiidikobraziko说。至少有5个人似乎不同意。