5

I was working on a stage when I noticed I practically had the exact same thing three times. Rather than that (since I hate that), I decided to take what I had those 3 times and turn it into a custom component.

Now I know I can add it in code but I can't predict the layout behavior (two of these will be going into tabs directly, and the third will be going into a grid pane).

I tried importing the .jar that contained the control into Scene Builder. A dialog popped up asking me what in the JAR I wanted to import but it was completely empty.

I've seen before that some individuals have added "custom controls" (a term which I use loosely) only to find that basically it just dumps a bunch of components together to form the control. That may work for some people but I'm not looking for that. To clarify

what I DO want (were I to look into the FXML code):

<DGCSDefiner //other layout related XML code/>

what I do NOT want:

<GridPane //bla bla XML layout code>
    <columnConstraints>
      //bla bla column constraint stuff
    </columnConstraints>
    //etc, etc
</GridPane>

Is this possible? I'm coming off of C# and VS2010 again and I'm a bit spoiled when it comes to custom controls so if it's at all possible to make something like that happen, can someone tell me how?

Is it possible to import a compiled JAR file containing a custom JavaFX control into Scene Builder, such that dropping it in from the library will result in what I described up there?

EDIT 1 Okay this is what I have in my FXML file. According to mlody991, I need 3 files to make this work: The FXML file (Built with SceneBuilder):

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<fx:root alignment="CENTER" hgap="5.0" styleClass="root" stylesheets="@DGCSDefiner.css" type="GridPane" vgap="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="DGCSDefiner.DGCSDefinerController">
   <children>
      <ComboBox fx:id="cbxColorStyle" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="150.0" promptText="Select Background Color Style" />
      <ColorPicker fx:id="cpSolidColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="32.0" prefWidth="283.0" visible="false" GridPane.rowIndex="1" />
      <StackPane fx:id="spSettings" styleClass="Group" GridPane.rowIndex="2" GridPane.vgrow="NEVER">
         <children>
            <GridPane fx:id="gpLinearSettings" hgap="5.0" styleClass="Group" vgap="20.0" visible="false">
               <children>
                  <Label text="Angle" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
                     <font>
                        <Font name="Arial" size="12.0" />
                     </font>
                  </Label>
                  <ComboBox fx:id="cbxLinearAngle" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="150.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
                  <Label text="1st Color" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
                  <ColorPicker fx:id="cpFirstLinearColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
                  <Label text="2nd Color" GridPane.halignment="RIGHT" GridPane.rowIndex="2" />
                  <ColorPicker fx:id="cpSecondLinearColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
               </children>
               <columnConstraints>
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
               </columnConstraints>
               <rowConstraints>
                  <RowConstraints minHeight="10.0" vgrow="NEVER" />
                  <RowConstraints minHeight="10.0" vgrow="NEVER" />
                  <RowConstraints minHeight="10.0" vgrow="NEVER" />
               </rowConstraints>
            </GridPane>
            <TabPane fx:id="tabRadialSettings" styleClass="Group" tabClosingPolicy="UNAVAILABLE" visible="false">
               <tabs>
                  <Tab closable="false" text="Colors">
                     <content>
                        <GridPane hgap="5.0" styleClass="Group" vgap="5.0">
                           <children>
                              <Label maxHeight="1.7976931348623157E308" text="1st Color" GridPane.vgrow="NEVER" />
                              <ColorPicker fx:id="cpFirstRadialColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.vgrow="NEVER" />
                              <Label maxHeight="1.7976931348623157E308" text="2nd Color" GridPane.rowIndex="1" GridPane.vgrow="NEVER" />
                              <ColorPicker fx:id="cpSecondRadialColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.vgrow="NEVER" />
                           </children>
                           <columnConstraints>
                              <ColumnConstraints hgrow="NEVER" minWidth="10.0" />
                              <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                           </columnConstraints>
                           <rowConstraints>
                              <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                              <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                           </rowConstraints>
                        </GridPane>
                     </content>
                  </Tab>
                  <Tab closable="false" text="Size and Position">
                     <content>
                        <GridPane hgap="5.0" styleClass="Group" vgap="5.0">
                           <children>
                              <Label text="H Position" />
                              <Label text="V Position" GridPane.rowIndex="1" />
                              <Label text="Radius" GridPane.rowIndex="2" />
                              <Slider fx:id="sliderHPos" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" GridPane.columnIndex="1" />
                              <Slider fx:id="sliderVPos" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                              <Slider fx:id="sliderRadius" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
                           </children>
                           <columnConstraints>
                              <ColumnConstraints hgrow="NEVER" minWidth="10.0" />
                              <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                           </columnConstraints>
                           <rowConstraints>
                              <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                              <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                              <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                           </rowConstraints>
                        </GridPane>
                     </content>
                  </Tab>
               </tabs>
            </TabPane>
         </children>
      </StackPane>
   </children>
   <columnConstraints>
      <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" vgrow="ALWAYS" />
   </rowConstraints>
</fx:root>

The Java Class file (which will represent the actual object in code):

package DGCSDefiner;

import java.io.IOException;
import static java.util.Arrays.asList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.control.TabPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;

public class DGCSDefiner extends Pane { //DigiGames Color Settings Definer.
    // Values injected by FXMLLoader
    //<editor-fold defaultstate="collapsed" desc="FXML Variables">
    //<editor-fold defaultstate="collapsed" desc="Containers">
    @FXML private GridPane  gpLinearSettings;   // fx:id="gpLinearSettings"
    @FXML private StackPane spSettings;         // fx:id="spSettings"
    @FXML private TabPane   tabsRadialSettings; // fx:id="tabRadialSettings"
    //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Color Pickers">
    @FXML private ColorPicker cpSolidColor,         // fx:id="cpSolidColor"
                              cpFirstLinearColor,   // fx:id="cpFirstLinearColor"
                              cpSecondLinearColor,  // fx:id="cpSecondLinearColor"
                              cpFirstRadialColor,   // fx:id="cpFirstRadialColor"
                              cpSecondRadialColor;  // fx:id="cpSecondRadialColor"
    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="Combo Boxes">
    @FXML private ComboBox<ColorStyles>     cbxColorStyle;  // fx:id="cbxColorStyle"
    @FXML private ComboBox<Integer>     cbxLinearAngle; // fx:id="cbxLinearAngle"
    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="Sliders">
    @FXMLprivate Slider     sliderRadius,   // fx:id="sliderRadius"
                            sliderHPos,     // fx:id="sliderHPos"
                            sliderVPos;     // fx:id="sliderVPos"
    //</editor-fold>
    //</editor-fold>
    private FXMLLoader Loader;

    @FXML // This method is called by the FXMLLoader when initialization is complete
    void initialize() {
        //<editor-fold defaultstate="collapsed" desc="Assertions">
        //<editor-fold defaultstate="collapsed" desc="Container Assertions">
        assert this.gpLinearSettings    != null : "fx:id=\"gpLinearSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.spSettings      != null : "fx:id=\"spSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.tabsRadialSettings  != null : "fx:id=\"tabsRadialSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="ColorPicker Assertions">
        assert this.cpSolidColor    != null : "fx:id=\"cpSolidColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.cpFirstLinearColor  != null : "fx:id=\"cpFirstLinearColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.cpSecondLinearColor != null : "fx:id=\"cpSecondLinearColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.cpFirstRadialColor  != null : "fx:id=\"cpFirstRadialColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.cpSecondRadialColor != null : "fx:id=\"cpSecondRadialColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="ComboBox Assertions">
        assert this.cbxColorStyle   != null : "fx:id=\"cbxColorStyle\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.cbxLinearAngle  != null : "fx:id=\"cbxLinearAngle\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Slider Assertions">
        assert this.sliderRadius    != null : "fx:id=\"sliderRadius\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.sliderHPos      != null : "fx:id=\"sliderHPos\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        assert this.sliderVPos      != null : "fx:id=\"sliderVPos\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";
        //</editor-fold>
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Initializations">
        //<editor-fold defaultstate="collapsed" desc="ComboBox Initializations">
        this.cbxColorStyle.getItems().addAll(
            asList(ColorStyles.values())
        );
        for (int x = 0; x < 8; x++)
            this.cbxLinearAngle.getItems().add(x * 45);
        this.cbxColorStyle.setOnAction(event -> {
            ColorStyles CS = this.cbxColorStyle.getValue();
            this.cpSolidColor.setVisible(CS == ColorStyles.SOLID);
            this.gpLinearSettings.setVisible(CS == ColorStyles.LINEAR);
            this.tabsRadialSettings.setVisible(CS == ColorStyles.RADIAL);
        });
        //</editor-fold>
        this.Loader = new FXMLLoader(
            this.getClass().getResource("DGCSDefiner.fxml")
        );
        this.Loader.setRoot(this);
        this.Loader.setController(this);
        //</editor-fold>
    }

    public DGCSDefiner(){
        try{ this.Loader.load(); }
        catch(IOException e){ throw new RuntimeException(e); }
    }

    /**
     * Get the ColorSettings defined by the control.
     * @return Defined Color Settings.
     */
    public ColorSettings getColorSettings(){
        if (this.cbxColorStyle.getSelectionModel().getSelectedIndex() < 0)
            return null;
        switch(this.cbxColorStyle.getValue()){
            case SOLID:
                return new ColorSettings(this.cpSolidColor.getValue());
            case LINEAR:
                return new ColorSettings(
                    this.cpFirstLinearColor.getValue(),
                    this.cpSecondLinearColor.getValue(),
                    this.cbxLinearAngle.getValue()
                );
            case RADIAL:
                return new ColorSettings(
                    this.cpFirstRadialColor.getValue(),
                    this.cpSecondRadialColor.getValue(),
                    (int)this.sliderRadius.getValue(),
                    (int)this.sliderHPos.getValue(),
                    (int)this.sliderVPos.getValue()
                );
        }
        return null; //This should never happen.
    }
    /** 
     * Load defined color settings.
     * @param cs Predefined color settings.
     */
    public void setColorSettings(ColorSettings cs){
        this.cbxColorStyle.setValue(cs.Style);
        switch(cs.Style){
            case SOLID:
                this.cpSolidColor.setValue(cs.clrPrimary);
                break;
            case LINEAR:
                this.cbxLinearAngle.setValue(cs.intAngle);
                this.cpFirstLinearColor.setValue(cs.clrPrimary);
                this.cpSecondLinearColor.setValue(cs.clrSecondary);
                break;
            case RADIAL:
                this.sliderRadius.setValue(cs.intSize);
                this.sliderHPos.setValue(cs.intHPos);
                this.sliderVPos.setValue(cs.intVPos);
                this.cpFirstRadialColor.setValue(cs.clrPrimary);
                this.cpSecondRadialColor.setValue(cs.clrSecondary);
        }
    }
}

And then this last file, the purpose of which eludes me:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package DGCSDefiner;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;

/**
 *
 * @author Will
 */
public class DGCSDefinerController implements Initializable {
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }
}

Is it possible for someone to explain to me the purpose of this last file? What is it's function? I can see from the example code with which I was furnished it has been set as the FXML Controller but that still tells me nothing. I've never really even set an FXML controller before since I typically do it in code, so is it's purpose explicitly to make this control importable into the Scene Builder?

EDIT 2 Okay. I had a hunch and it proved correct but it did not help. I removed the control CSS stylesheet reference and it allowed me to add the control, no problem.

However when I dropped it in this was what happened in the FXML file:

It went from this (Relevant portion only shown):

<Tab fx:id="tabBGStyle" closable="false" text="Background" />

to this:

<Tab fx:id="tabBGStyle" closable="false" text="Background">
    <content>
        <GridPane alignment="CENTER" hgap="5.0" styleClass="root" vgap="5.0">
            <children>
                <ComboBox fx:id="cbxColorStyle" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="150.0" promptText="Select Background Color Style" />
                <ColorPicker fx:id="cpSolidColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="32.0" prefWidth="283.0" visible="false" GridPane.rowIndex="1" />
                <StackPane fx:id="spSettings" styleClass="Group" GridPane.rowIndex="2" GridPane.vgrow="NEVER">
                    <children>
                        <GridPane fx:id="gpLinearSettings" hgap="5.0" styleClass="Group" vgap="20.0" visible="false">
                            <children>
                                <Label text="Angle" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
                                    <font>
                                        <Font name="Arial" size="12.0" />
                                    </font>
                                </Label>
                                <ComboBox fx:id="cbxLinearAngle" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="150.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
                                <Label text="1st Color" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
                                <ColorPicker fx:id="cpFirstLinearColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
                                <Label text="2nd Color" GridPane.halignment="RIGHT" GridPane.rowIndex="2" />
                                <ColorPicker fx:id="cpSecondLinearColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
                            </children>
                            <columnConstraints>
                                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                            </columnConstraints>
                            <rowConstraints>
                                <RowConstraints minHeight="10.0" vgrow="NEVER" />
                                <RowConstraints minHeight="10.0" vgrow="NEVER" />
                                <RowConstraints minHeight="10.0" vgrow="NEVER" />
                            </rowConstraints>
                        </GridPane>
                        <TabPane fx:id="tabRadialSettings" styleClass="Group" tabClosingPolicy="UNAVAILABLE" visible="false">
                            <tabs>
                                <Tab closable="false" text="Colors">
                                    <content>
                                        <GridPane hgap="5.0" styleClass="Group" vgap="5.0">
                                            <children>
                                                <Label maxHeight="1.7976931348623157E308" text="1st Color" GridPane.vgrow="NEVER" />
                                                <ColorPicker fx:id="cpFirstRadialColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.vgrow="NEVER" />
                                                <Label maxHeight="1.7976931348623157E308" text="2nd Color" GridPane.rowIndex="1" GridPane.vgrow="NEVER" />
                                                <ColorPicker fx:id="cpSecondRadialColor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.vgrow="NEVER" />
                                            </children>
                                            <columnConstraints>
                                                <ColumnConstraints hgrow="NEVER" minWidth="10.0" />
                                                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
                                            </columnConstraints>
                                            <rowConstraints>
                                                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                            </rowConstraints>
                                        </GridPane>
                                    </content>
                                </Tab>
                                <Tab closable="false" text="Size and Position">
                                    <content>
                                        <GridPane hgap="5.0" styleClass="Group" vgap="5.0">
                                            <children>
                                                <Label text="H Position" />
                                                <Label text="V Position" GridPane.rowIndex="1" />
                                                <Label text="Radius" GridPane.rowIndex="2" />
                                                <Slider fx:id="sliderHPos" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" GridPane.columnIndex="1" />
                                                <Slider fx:id="sliderVPos" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                                                <Slider fx:id="sliderRadius" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="1.0" showTickMarks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
                                            </children>
                                            <columnConstraints>
                                                <ColumnConstraints hgrow="NEVER" minWidth="10.0" />
                                                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                            </columnConstraints>
                                            <rowConstraints>
                                                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                            </rowConstraints>
                                        </GridPane>
                                    </content>
                                </Tab>
                            </tabs>
                        </TabPane>
                    </children>
                </StackPane>
            </children>
            <columnConstraints>
                <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" vgrow="ALWAYS" />
            </rowConstraints>
        </GridPane>
    </content>
</Tab>

which is exactly what I DO NOT WANT.

What I would like to see is something to the effect of this:

<Tab fx:id="tabBGStyle" closable="false" text="Background">
    <content>
        <DGCSDefiner/>
    </content>
</Tab>

in the FXML code after I drag and drop the custom control into the designer. Is that possible? Do I need to compile it into a jar?

Edit 3 To make it a bit more clear, this is exactly what I want to see happen. This looks good but the problem is there is no information about how to import a custom control into Scene Builder such that when I Drag 'n Drop it onto the canvas, I only get somewhere in the neighborhood of a single line of code, vs the book and a half it's writing (which is just silly. If I wanted that I could (and would) do it myself).

Will
  • 3,413
  • 7
  • 50
  • 107

1 Answers1

5

You do not need .jar file to do that. You can simply create new FXML file with that what you need ex. combo box. Create class file with extending combo box, controller and add controller in FXML file (in scene builder).

Find "Import from JAR/FXML file" in combo box near to left search box in scene builder and then select the file. Now you have new title pane in left accordion with name Custom. There you can find your components.

@edit There are files.

MyGridPane.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<fx:root type="javafx.scene.layout.GridPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"  xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="MyGridPane.MyGridPaneController">
  <columnConstraints>
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
  </columnConstraints>
  <rowConstraints>
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
  </rowConstraints>
</fx:root>

MyGridPane.java

package MyGridPane;

import javafx.fxml.FXMLLoader;
import java.io.IOException;

/**
 * Created by Marcin on 2014-09-01.
 */
public class MyGridPane {
    MyGridPane(){
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MyGridPane.fxml"));
        fxmlLoader.setRoot(this); fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

MyGridPaneController.java

package MyGridPane;

import javafx.fxml.Initializable;

import java.net.URL;
import java.util.ResourceBundle;

/**
 * Created by Marcin on 2014-09-01.
 */
public class MyGridPaneController implements Initializable{
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }
}

Next step is add to Scene Builder

enter image description here

and you can add this component.

enter image description here

Marcin Lagowski
  • 628
  • 2
  • 12
  • 26
  • Tried that. Got a message saying "Objects cannot be added to the Library because they are not self-contained". – Will Sep 01 '14 at 20:59
  • Except that control is overly simplified compared to that with which I am working. I don't know that it would work. My control is effectively a bunch of component organized together that I want to be able to re use again and again, and what I see you have is just a grid pane. Would putting controls in that GridPane make it importable, or would it still fail completely? – Will Sep 01 '14 at 22:07
  • It is simple example, in my projects I use more complicated components. Panes/HBox/... with buttons, combo boxes etc. It doesn't matter. It have to work fine without any trouble. Just use three files like here, and there is no problem to reuse more complicated components. – Marcin Lagowski Sep 01 '14 at 23:08
  • oh i see. you need to separate the controller... that makes sense i guess. What is the purpose of the MyGridPaneController.java file? How/why would I use that? – Will Sep 02 '14 at 03:52
  • Was able to get it to import but it's doing what I don't want it to do. It's basically building the entire control from scratch with every individual component, instead of treating the entire component as a single control. This is exactly what I am trying to avoid. Still, it is a step closer. – Will Sep 02 '14 at 04:40
  • Any progress on this? i tried making a jar, but scenebuilder can't seem to find the fxml resource loaded by my class in the jar – Jody Sowald May 31 '22 at 16:27