Contents
Introduction
JavaFx, although being far from perfect (whyyyy all those -fx prefixed “css” properties?) is definitely better than any of the previous attempts at Java desktop apps.
Historically, Java has always put the “ewwwy” in GUI, and the incredibly programmatic approach taken by the other major desktop frameworks is somewhat intimidating.
JavaFx, in an unexpected-yet-welcomed programmer-friendly approach, can get away with primarily using FXML and “CSS” – that is, its own XML-based mark up language and almost CSS for styling.
Despite all of this, you’ll still find yourself laying out the same input forms over and over again. It gets dull. Computers should do the dull work, not us.
LazyFX
LazyFx is a first-blush attempt at getting around this. Point it at a POJO, or a slightly annotated POJO for better results, and it will attempt to generate a Pane containing all the fields necessary to populate that POJO.
Point it at a generated Pane, and it’ll recreate the POJO from it. Fairly quick, hopefully easy.
The framework itself is available on GitHub.
Example
POJO
Let’s take the following example POJO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public class SampleClass { private String textString; private int aNumber; private String somePath; private String someStrings; @Name(value = "A string", prompt = "Enter some string here") public String getTextString() { return textString; } public void setTextString(String textString) { this.textString = textString; } @Name("An integer") public int getaNumber() { return aNumber; } public void setaNumber(int aNumber) { this.aNumber = aNumber; } @Type(EType.PATH) public String getSomePath() { return somePath; } public void setSomePath(String somePath) { this.somePath = somePath; } @Type(value = EType.COLLECTION, tag = "range") public String getSomeStrings() { return someStrings; } public void setSomeStrings(String someStrings) { this.someStrings = someStrings; } } |
We have four main things here – a string, an integer, a file path and a value called some strings which we want to store a choice in.
We want a normal TextField for the String , a TextField accepting only integers for the int , a path and a file browser for the path and a drop-down ComboBox for the choice.
The String doesn’t actually need any annotations, but I’ve put down a @Name annotation here just to make a more user-friendly experience. It improves the displayed name, which would otherwise be "TextString" , and it specifies some prompt text to be placed inside the TextField .
Likewise with the int, we specify just a name. The distinction between generating a normal TextField and a digits-only one is done by the framework based on the return type.
The path is shown here as just a String , but the presence of the @Type annotation changes how it’s generated slightly. In read-only mode, it’ll be generated as a Label (in the same way that a String would be), but normally it’ll be generated as a TextField with a Browse button that will launch a directory chooser.
Finally, we have our choice option. Its @Type annotation specifies that it’s a Collection , and specifies a tag. This tag refers to an object we include when we generate the GUI, that will populate the ComboBox .
Generate the GUI
To generate the actual GUI, we use the JavaFXComponent class.
1 2 3 4 5 6 7 8 9 |
TaggedParameters taggedParameters = new TaggedParameters(); List<String> range = new ArrayList<>(); range.add("Ay"); range.add("Bee"); range.add("See"); taggedParameters.addTag("range", range); Pane build = JavaFXComponent.build(new SampleClass(), taggedParameters, window); mainPane.getChildren().add(build); |
We declare the collection for the drop-down, then pass a new instance of the class to the component along with the tagged parameters and the window. This generates the GUI, which we can add to our main pane, producing the following.
Easy enough?
Read in the GUI
To read the values back in, we take the node that we added the generated GUI to and call read on it. Modifying our original code to have a button,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
TaggedParameters taggedParameters = new TaggedParameters(); List<String> range = new ArrayList<>(); range.add("Ay"); range.add("Bee"); range.add("See"); taggedParameters.addTag("range", range); Pane build = JavaFXComponent.build(new SampleClass(), taggedParameters, window); Button button = new Button("Read in"); button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { SampleClass sample = JavaFXComponent.read(mainPane, SampleClass.class); System.out.println(sample.getTextString()); } }); mainPane.getChildren().addAll(build, button); |
After JavaFXComponent.read(mainPane, SampleClass.class); we are presented with a populated POJO.
Conclusion
LazyFX is the start of the way to make, if not beautiful GUIs, really really quick GUIs, then read them in again. It works fairly nicely with predictable, dull pages (like settings), but can be adapted to work with more.
Post here if you have any questions, or feel free to fork the project.
Leave a Reply