With the release of Scene Builder 2.0 it is now much easier to add custom and 3rd party JavaFX controls to the component palette.
There are a couple of different strategies to add a custom component to Scene Builder, and this blog post will illustrate creating a custom component with FXML and importing the FXML file into Scene Builder so the custom component can be used within Scene Builder itself.
To start with, I’ll create a simple custom component in Scene Builder which will consist of a Button and a Label, which I have cleverly named a ButtonLabel. A screenshot of Scene Builder with the fancy new custom component is below.
Below is the FXML that SceneBuilder generates. As you can see I have an action defined on the button, but no controller defined for the component. This is because the button will end up pointing to whatever controller the Scene that this component gets bundled into. The other thing to note is that this FXML file contains no references to stylesheets or outside images.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="70" fx:id="label" />
</children>
</AnchorPane>
Now to add the new component to Scene Builder so it can be added to an application, you must import the FXML file into Scene Builder by selecting the icon next to the search box at the top of the Library Pane.
Browse the the FXML file of the custom component.
The ButtonLabel now appears in the Custom section of the library and can be dragged onto the new Scene.
Below is the code that is generated by Scene Builder for the new Scene with the LabelButton. As can be viewed below, Scene Builder simply imports the custom FXML code into the new scene, and also adds the #handleButtonAction to the com.lynden.myapp.FXMLController class.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="379.0" prefWidth="442.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="com.lynden.myapp.FXMLController">
<children>
<TableView layoutX="40.0" layoutY="28.0" prefHeight="200.0" prefWidth="356.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
<AnchorPane id="AnchorPane" layoutX="108.0" layoutY="256.0" prefHeight="109.0" prefWidth="220.0">
<children>
<Button fx:id="button" layoutX="172.0" layoutY="43.0" onAction="#handleButtonAction" text="Click Me!" AnchorPane.rightAnchor="10.0" />
<Label fx:id="label" layoutX="14.0" layoutY="31.0" minHeight="16" minWidth="69" prefHeight="47.0" prefWidth="100.0" text="Custom Text" />
</children>
</AnchorPane>
</children>
</AnchorPane>
twitter: @RobTerp
What happens when I make changes to the custom component? Is there any way to update all the places the custom component is already being used?
With this strategy, changes to the custom component do not carry over to the places where that custom component is already in use. In order to do this you will want to follow a strategy similar to a previous post
http://rterp.wordpress.com/2013/09/13/creating-custom-javafx-components-with-scene-builder-and-fxml/
and then import the .jar file into Scene Builder. I will blog about this to show how to do it at some point in the not too distant future.
Thank you. 🙂
Nice post! The other way to reuse custom components is to implement custom Controls. The only way to use it into Scene Builder is to importing a JAR that contains all the classes of the Control. The problem is, that every time a change is made on the Control, it must be exported as JAR and imported into Scene Builder. This takes long time. Have you an idea how point Scene Builder to the source folder, so it can import the Control without the need of packaging all into a JAR?
As far as I can tell this isn’t possible to do with Scene Builder 2. I’ve tried copying the component’s .jar file directly to the .scenebuilder/Library folder. I can see new components in the palette, however any existing custom components on the UI are not rendered by Scene Builder even though they are referenced in the FXML file. I’d be interested to hear if anyone has found any workarounds to this issue.
Thanks for trying it! I’ve took a look into the JavaDoc of the SceneBuilder Kit 2.0 but I don’t see any method for importing a JAR automatically. There is no LibraryPanelController#performImportJar method or the like to do that.
Reblogged this on Dinesh Ram Kali..
If I understand correctly, all this feature does is allow you to cut and paste bits of FXML files around. Isn’t there a way of including your own component? Let’s say you had a GPS locator component that display your current position – could you add that to the palette?
Yes, there’s a way to do this. I’ll start working on another short tutorial to demonstrate how to do it.
-Rob
Thx!
Pingback: Adding Custom JavaFX Component to Scene Builder 2.0 (Part 2) | Rob's Blog
thanks for these instructions. I am searching an easy way to include treeviewcheckboxes and treeviewcomboboxes into scene builder. do you think that this is possible similar to the way you explained here?
Yes, Absolutely!
thanks for your sharing, but i still don’t know how to solve “Controller value already specified” when i click button in other scene………..
Thank you.