Java SceneBuilder自定义控件类路径

Java SceneBuilder自定义控件类路径,java,javafx,javafx-8,scenebuilder,Java,Javafx,Javafx 8,Scenebuilder,我对SceneBuilder和javafx处理自定义控件的方式已经束手无策 我是使用fx:root还是不使用它?我选择使用它。如此内在 控制器+控件的根类,我将其自身设置为根 和控制器,正如所需。但它仍然说“根没有 已设置。请在加载之前使用方法setRoot() 在将容纳自定义控件的父FXML中,我是什么 应该进口吗 什么是正确的类路径,以便我可以显示我的自定义 SceneBuilder2.0中的控件?我不太明白这个问题 “/…/…/…/…/bin”之类的东西 有了新的标签,是否需要使用 在标记

我对SceneBuilder和javafx处理自定义控件的方式已经束手无策

  • 我是使用fx:root还是不使用它?我选择使用它。如此内在 控制器+控件的根类,我将其自身设置为根 和控制器,正如所需。但它仍然说“根没有 已设置。请在加载之前使用方法setRoot()

  • 在将容纳自定义控件的父FXML中,我是什么 应该进口吗

  • 什么是正确的类路径,以便我可以显示我的自定义 SceneBuilder2.0中的控件?我不太明白这个问题 “/…/…/…/…/bin”之类的东西

  • 有了新的
    标签,是否需要使用
    在标记中了吗

  • 到目前为止,我的自定义控件只不过是一个进度指示器,以避免复杂性

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.layout.HBox?>
    
    
    <fx:root type="HBox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
       <children>
          <ProgressBar fx:id="progressBar" prefWidth="200.0" progress="0.0" />
       </children>
    </fx:root>
    
    package application.ctrl;
    
    import java.io.IOException;
    
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.control.ProgressIndicator;
    import javafx.scene.layout.HBox;
    import application.Main;
    
    父FXML:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.text.*?>
    <?import javafx.geometry.*?>
    <?import java.lang.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.layout.VBox?>
    <?import application.ctrl.ProgressSelector?>
    
    <VBox fx:id="vbox" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ctrl.ObjectiveEditorCtrl">
       <children>
          <HBox>
             <children>
                <Button mnemonicParsing="false" onAction="#back" text="&lt;" />
                <Label text="Editing Objective:" />
             </children>
          </HBox>
          <TextField fx:id="objectiveName" />
          <ProgressSelector />
          <HBox>
             <children>
                <Label text="Planned Start:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="plannedStart" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Actual Start:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="actualStart" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Planned Finish:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="plannedFinish" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Actual Finish:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="actualFinish" />
             </children>
          </HBox>
          <HBox alignment="CENTER_RIGHT">
             <children>
                <Button mnemonicParsing="false" onAction="#save" text="Save" />
                <Button mnemonicParsing="false" onAction="#back" text="Cancel" />
             </children>
          </HBox>
       </children>
       <padding>
          <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
       </padding>
    </VBox>
    
    这里有很多问题

    1-使用fx:root可以自定义FXMLLoader,您可以更改实例化组件的方式:

    但是,对于SceneBuilder 2,它根本无法正常工作!场景生成器2的“规范”方式(与1配合良好)似乎不使用fx:root

    2-这取决于您在1中选择的模式。可以是FXML中带有显式导入的自定义java组件,也可以使用FXML:include。首先是FXML,然后是控制器。或者抽象组件(控制器为fx:root),然后是FXML

    3-SceneBuilder 2在类加载器方面有很多问题,因为每个自定义组件都加载了一个不同的类加载器,这意味着您将在大量未找到类的情况下运行,就像异常一样。解决此问题的一种方法是fork SceneBuilder强制所有自定义组件仅使用一个类加载器:

    或者等待修复。或者不使用fx:root并首选fx:include。或者根本不使用场景生成器,这对于许多人来说都是一个有效的解决方案

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.text.*?>
    <?import javafx.geometry.*?>
    <?import java.lang.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.layout.VBox?>
    <?import application.ctrl.ProgressSelector?>
    
    <VBox fx:id="vbox" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ctrl.ObjectiveEditorCtrl">
       <children>
          <HBox>
             <children>
                <Button mnemonicParsing="false" onAction="#back" text="&lt;" />
                <Label text="Editing Objective:" />
             </children>
          </HBox>
          <TextField fx:id="objectiveName" />
          <ProgressSelector />
          <HBox>
             <children>
                <Label text="Planned Start:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="plannedStart" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Actual Start:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="actualStart" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Planned Finish:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="plannedFinish" />
             </children>
          </HBox>
          <HBox>
             <children>
                <Label text="Actual Finish:" />
                <Region HBox.hgrow="ALWAYS" />
                <DatePicker fx:id="actualFinish" />
             </children>
          </HBox>
          <HBox alignment="CENTER_RIGHT">
             <children>
                <Button mnemonicParsing="false" onAction="#save" text="Save" />
                <Button mnemonicParsing="false" onAction="#back" text="Cancel" />
             </children>
          </HBox>
       </children>
       <padding>
          <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
       </padding>
    </VBox>
    
    package application.ctrl;
    
    import interfaces.ControlledScreenInterface;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.DatePicker;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.VBox;
    import application.ScreenController;
    import application.objects.Objective;
    
    public class ObjectiveEditorCtrl implements Initializable,
            ControlledScreenInterface {
    
        @FXML
        private TextField objectiveName;
        @FXML
        private ProgressSelector completion;
        @FXML
        private DatePicker plannedStart;
        @FXML
        private DatePicker plannedFinish;
        @FXML
        private DatePicker actualStart;
        @FXML
        private DatePicker actualFinish;
        @FXML
        private VBox vbox;
    
        private ScreenController parent;
        private Objective current;
    
    
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            // TODO Auto-generated method stub
    
        }
    
    
    
        public void init(Objective current) {
            this.current = current;
            objectiveName.setText(current.getName());
            // completion.setProgress(current.getCompletion());
            plannedStart.setValue(current.getPlannedStart());
            actualStart.setValue(current.getActualStart());
            plannedFinish.setValue(current.getPlannedFinish());
            actualFinish.setValue(current.getActualFinish());
        }
    
    
    
        public void save() {
            // current.setName(objectiveName.getText());
            // // current.setCompletion(completion.getProgress());
            // current.setPlannedStart(plannedStart.getValue());
            // current.setPlannedFinish(plannedFinish.getValue());
            // current.setActualStart(actualStart.getValue());
            // current.setActualFinish(actualFinish.getValue());
            // back();
        }
    
    
    
        public void back() {
            parent.back();
        }
    
    
    
        @Override
        public void setParentScreen(ScreenController parent) {
            this.parent = parent;
        }
    }