Skip to content
Mthec edited this page Nov 18, 2015 · 1 revision

FXML

As well as creating the UI in code as in the interface examples, if you want something more complex, or just want to see it laid out before you add it to the launcher you can load an .fxml file instead. Whilst you could write the file by hand, it would probably be easier if you download Scene Builder and use it to to help you make layouts.

Usage

An .fxml file looks something like this:

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

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.VBox?>
<VBox prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="mod.wurmonline.MyController">
    <children>
        <TextField fx:id="nameText" promptText="Enter name" />
        <Button fx:id="saveButton" mnemonicParsing="false" onAction="#saveButtonClicked" text="Save" />
    </children>
</VBox>

If you use Scene Builder, make sure to set controller in the bottom left of the window. This is what connects your layout to your code.

package mod.wurmonline;

import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.Pane;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import mod.wurmonline.serverlauncher.gui.ServerGuiController;
import org.gotti.wurmunlimited.modloader.interfaces.WurmMod;
import org.gotti.wurmunlimited.modloader.interfaces.WurmUIMod;

public class MyController implements WurmMod, WurmUIMod {
    ServerGuiController guiController;

    public Region getRegion(ServerGuiController guiController) {
        controller = guiController;

        try {
            FXMLLoader fx = new FXMLLoader(MyController.class.getResource("MyLayout.fxml"));
            fx.setClassLoader(this.getClass().getClassLoader());
            return (Region)fx.load();
        } catch (IOException ex) {
            logger.log(Level.SEVERE, ex.getMessage(), ex);
            Pane pane = new Pane();
            Label label = new Label("Players.fxml was not loaded.");
            pane.getChildren().add(label);
            return pane;
        }
    }
}

Because this layout is not the main window, you have to add a step in between what you'd normally do to load an .fxml. So after creating a new FXMLLoader you need to setClassLoader to your class' classloader, otherwise it will try and find it on the launcher controller. The catch section isn't necessarily needed, however if for some reason it does not find the .fxml file it will stop it bringing the whole launcher down. Not that I had that happen to me...

    @FXML
    TextField nameText;
    @FXML
    Button saveButton;

    @FXML
    void saveButtonClicked() {
        saveButton.setDisable(true);
        String text = nameText.getText();
        // Save text somewhere.
    }

When you have your .fxml file loaded, you can access any of the items you set a name for by adding @FXML above them. Same goes for methods, when a button is clicked it will call the method of the controller specified in the onAction="" attribute. However not all items have onAction, in which case you need to look into creating a ChangeListener. Any items that allow the user to enter or alter information have getText or getValue or similar. By keeping a reference to the button as well you can enable or disable it depending on how your mod works.

Further Reading

If you want to see some more involved examples, have a look at the following mods that come with the launcher: