简体   繁体   中英

How do I set up a JavaFX Control to be imported into Scene Builder?

I have a JavaFX control that is basically an amalgamation of several other JavaFX controls.

I want it such that the .jar file can be imported into Scene Builder so that it can be used like any other control. The closest analogy I can think of is when you make a custom control in C# and use it several times throughout several projects.

When I try to import the FXML file, it doesn't work. The control isn't treated as a single entity, and instead is basically just all of it's parts strung out in the FXML file.

What do I need to do with the FXML file, or the controller.java file so that the Scene Builder will be able to import the .jar, see the control(s), and allow me to import and use each custom control as a single entity? I've looked several places and even asked on Stack Overflow once before (though the answer I got was not the one for which I was looking, and have received no responses since), but nothing I've seen comes close to handling my issue.

The closest I've come has to do with this line in the FXML file:

<?scenebuilder-classpath-element /path/to/something?>

but I don't know what goes in /path/to/something

I know I can, in the initialization, simply add the control to the scene, but that is sub-optimal and something which I am desperately trying to avoid.

I was finally able to resolve the issue. After much trial and error and following the sample code that came from here , I discovered my problem was that I needed 2 classes for each FXML control group. One to be the actual controller of the group, and another to be the object that would house the controller. I followed the code in the Unlock example and it was a godsend for helping me. Basically it comes down to two files:

The object (which extends the type of the root node, in my case):

public class <InsertObjectClassNameHere> extends <RootContainerTypeHere>{
}

After that you need the controller class. This is with what I am most familiar, however I was still doing it wrong. This is what needs to implement initializable :

public class <InsertControllerClassNameHere> implements Initializable{

}

So for me the Object class looks like this:

public class DGCSDefiner extends GridPane {
    private final DGCSDefinerController Controller;
    public DGCSDefiner(){
        this.Controller = this.Load();
    }

    private DGCSDefinerController Load(){
        final FXMLLoader loader = new FXMLLoader();
        loader.setRoot(this);
        loader.setClassLoader(this.getClass().getClassLoader());
        loader.setLocation(this.getClass().getResource("DGCSDefiner.fxml"));

        try{
            final Object root = loader.load();
            assert root == this;
        } catch(IOException ex){
            throw new IllegalStateException(ex);
        }

        final DGCSDefinerController cntrlr = loader.getController();
        assert cntrlr != null;
        return cntrlr;
    }

    /**
     * Get the settings defined by the controller.
     * @return controller defined settings.
     */
    public ColorSettings getColorSettings(){
        return this.Controller.getColorSettings();
    }

    /**
     * Set the controllers color settings.
     * @param CS Defined color settings.
     */
    public void setColorSettings(ColorSettings CS){
        this.Controller.setColorSettings(CS);
    }
}

and then there is the actual Controller class.

So for a straight-forward answer,

you need to have a class that will be loading your controller, and you need to pass down from your controller to that class that with which you will be working (Or, you can simply keep the controller public and access it directly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM