Hello Today after long days I’ve came here to share my experience of FXML in JavaFX. After working with FXML I found it’s really easy for every developer.

Requirements:

  •  XML knowledge
  •  CSS knowledge

FXML and Binding Stuff

Ok First lets start with a FXML Template.

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<?import fxmlstuff.fxml.*?>

<GUITemplate id="main" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="fxmlstuff.fxml.GUITemplate">
    <children>       
        <Rectangle fx:id="back" />        
        <Rectangle fx:id="front" /> <Button fx:id="button" text="Click Me" onAction="#handleButton"/>
        <Button fx:id="clear" text="Clear Me" onAction="#handleClearButton"/>
        <TextArea fx:id="textArea"/>        
    </children>
</GUITemplate>

In above FXML I’ve not added Rectangle,Button,TextArea controls.
As per the FXML specification you can call the function from the FXML attribute using ‘#’ just before the function name. Here I’ve added #handleButton() and #handleClearButton() functions to handle the event of Buttons. Here First we are going to load them in JavaFX Application moreover we are going to make the Rectangle flexible to the Stage‘s width and height. To make any shapes or controls width and height relative to the Stage‘s width, height we can use bind feature plus a the control or the shape which we are going to make bind must static. Ok now we are going to need one Controller for the FXML which helps to control the FXML GUI components. I’ve already added fx:controller = "fxmlstuff.fxml.GUITemplate" in above FXML. So to map the controller we ought to make one conroller class inside fxmlstuff.fxml package with classname GUITemplate.java

GUITemplate.java

public class GUITemplate extends StackPane implements Initializable {

	//Main GUI Components
	@FXML
    private Button button,clear;
    @FXML
    private Rectangle back,front;    
    @FXML
    private TextArea textArea;	

	//Helper Properties 
    @FXML
    private static DoubleProperty widthX = new SimpleDoubleProperty(500);
    @FXML
    private static DoubleProperty heightX = new SimpleDoubleProperty(500);

	//static access to the Helper Properties
    public static DoubleProperty heightXProperty() {
        return heightX;
    }

    public static DoubleProperty widthXProperty() {
        return widthX;
    }

    //Button Action Handling    
    public void handleButton(ActionEvent ac){
        textArea.appendText("\n Yes you clicked");
    }

    public void handleClearButton(ActionEvent ac){
        textArea.setText("==============================\n"
                + "  Welcome to the Console of JavaFX\n"
                + "==============================\n"); 
    }

    //Main Initialization
    @Override
    public void initialize(URL url, ResourceBundle rb) {  

    }    
}

In above Java controller I’ve not done anything. Just made the instances. We’ll need to customize our controller class to make things working greatly.You can see there are eventHandler for the buttons also. I just want you to know that I’ve made some variables static which is useful for binding with Stage width and height. Here one more Java class we need to add i.e. FXMLStuff.java a.k.a main executor class.

public class FXMLStuff extends Application{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        GUITemplate tpl = (GUITemplate) FXMLLoader.load(getClass().getResource("fxml/GUITemplate.fxml"));
        Scene scene = new Scene(tpl,500,500);      
        scene.getStylesheets().add(getClass().getResource("fxml/gui.css").toExternalForm());

        GUITemplate.heightXProperty().bind(stage.heightProperty());
        GUITemplate.widthXProperty().bind(stage.widthProperty()); 

        GUITemplate.loadOnStart();

        stage.setScene(scene);
        stage.show();

    }

}

As you can see on the main executor class there we’ve bind the property with respect to the Stage’s width and height. Currently If you compile them you won’t be able to see any thing magic. So to make thing work let’s touch with CSS. Let’s attach some css with our controller and css. Here we are again back to controller class.

GUITemplate.java(some edit)

@Override
    public void initialize(URL url, ResourceBundle rb) {        
        //--------------
        //Some bindings
        //--------------
        back.widthProperty().bind(widthX.subtract(50));
        back.heightProperty().bind(heightX.subtract(100));

        front.heightProperty().bind(back.heightProperty().subtract(100)); 
        front.widthProperty().bind(back.widthProperty().subtract(100)); 

        textArea.maxHeightProperty().bind(front.heightProperty());
        textArea.maxWidthProperty().bind(front.widthProperty()); 

        //---------
        //Some CSS
        //---------
        back.getStyleClass().addAll("rect","back-rect");
        front.getStyleClass().addAll("rect","front-rect"); 
        button.getStyleClass().add("control"); 
        clear.getStyleClass().add("control"); 
        textArea.getStyleClass().add("text-area"); 

        //StackPane aligns and margins
        StackPane.setAlignment(button, Pos.BOTTOM_RIGHT);
        StackPane.setAlignment(clear, Pos.BOTTOM_LEFT);
        StackPane.setMargin(button, new Insets(0,70,50,0));
        StackPane.setMargin(clear, new Insets(0,0,50,70));

    }

I’ve add some bindings to make the rectangle and control to be updated according to the Stage’s width and height. Also I’ve added some css class to customize the default controls color and style. Finally I did alignment for the clear and button Button to the left and right with some margins.

CSS Stuffs

Now we can head towards CSS for our design.

/*
  Class for both buttons
*/
.control{
    -fx-base:#404040;
    -fx-outer-border:gray;    
    -fx-focus-color: derive(gray,10%);
}
/*
  Class default text area 
*/
.text-area{
    -fx-outer-border:transparent;    
    -fx-focus-color: transparent;
    -fx-text-box-border:transparent;
    -fx-shadow-highlight-color:transparent;
    -fx-control-inner-background:transparent; 
}

/*
  Class for both rectangles
*/
.rect{
    -fx-fill:#f3f3f3;    
    -fx-opacity:1;
    -fx-effect: dropshadow(two-pass-box , black, 5, 0.0 , 0, 1);
    -fx-arc-width: 20;
    -fx-arc-height: 20;
}
/*
  Class for both front Yellow rectangle
*/
.front-rect{        
    -fx-effect: innershadow(two-pass-box , black, 7, 0 , 0,1);
    -fx-fill: linear-gradient(to bottom, derive(#fdffbb,0%), #fcea72) ;
}
/*
  Class for both back black rectangle
*/
.back-rect{    
    -fx-fill: linear-gradient(to bottom, derive(#4d4d4d,0%), #0b0b0b);
}

If you are new to CSS of javafx then please have a look at this CSS reference: CSS Ref
Now If compile and run this program you will output like this:

FXML Stuffs

If you like more like run some Java code during initialization of the FXML then Yes, you can do it! You just need to make things static so that it is accesible by the main-executor class or other class to run specific java task inside FX Thread.

GUITemplate.java( Added Java Task inside initialize )

//....
public static void loadOnStart(){
	textArea.setText("==============================\n"
			+ "  Welcome to the Console of JavaFX\n"
			+ "==============================\n"); 
	Task task = new Task<Void>(){
		@Override
		protected Void call() throws Exception {
			//Timer t = new Timer();

			Timer timer = new Timer(5000,new ActionListener(){

				@Override
				public void actionPerformed(java.awt.event.ActionEvent ae) {
					textArea.appendText("\n : 5 second gone...");
				}

			});
			timer.start();               
			return null;
		}

	};
	new Thread(task).start();

}

@Override
public void initialize(URL url, ResourceBundle rb) {
	//..codes of previous
	loadOnStart();
}
//...

Now load them inside initialize of the FXController or load them from the Main executor class as per your requirement. I’ve loaded them insize initialize of the GUITemplate.java. Now you can see that the “: 5 second gone..” is printed in TextArea every 5 second which is the Java thread.

FXML Stuffs

Project Source Code : FXMLStuff.zip

Ok Thanks for watching the blog. Please feel free for comment.
Have a :) good day