0

I'm new to JavaFX, and until now, I've only been using FXML and Scene Builder for building UIs. However, I encountered some performance issues regarding FXMLoader along the way. So I considered looking up some solutions, I wanted to try building UIs using Java code. Found out the Builder API which looked so nice but unfortunately was deprecated. Meanwhile, in the proposal concerning Builders deprecation, the author proposed this approach using lambda expressions which looks pretty decent to me

Group g = new Group(gg -> {
    gg.getChildren().addAll(new Button(b -> {
        b.setText("Hello");
    });
});

I tried this code on, but the IDE doesn't recognize .getChildren()

What's wrong with this code?

  • Perhaps you can add what import you are using in the file and the version of the library you are using. From what I see at first, it looks like the `Group` constructor cannot accept a lambda as argument. – acejazz Jun 22 '21 at 21:40
  • For reference, this self-contained [example](https://stackoverflow.com/a/31909942/230513) is a rote transliteration of the original `Builder` approach – trashgod Jun 22 '21 at 21:55
  • You say this came from a proposal. Was that an API proposal? If so, was it accepted at any point. I suppose I’m asking which `Group` constructor and which `Button` constructor this is supposed to be using. – James_D Jun 23 '21 at 01:09
  • Also *”I encountered some performance issues using `FXMLLoader`”*. You really shouldn’t be using that frequently, so that’s really a sign that you code is not well designed. Maybe it’s better/easier to fix the underlying design issue? – James_D Jun 23 '21 at 01:10

2 Answers2

1

"What's wrong with this code?"

The constructors you're invoking simply don't exist. There are three Button constructors, taking either no parameters, a String (the text), or a String and a Node (text and graphic). Since String is not a @FunctionalInterface (or an interface with a single abstract method) there is no constructor matching the Button constructor you are trying to call.

Similarly, there are three Group constructors, and again none of them match the constructor you are trying to call (which would require a single parameter which was an interface type with a single abstract method).

So the proposal you read was simply that: an API proposal that was never adopted.

James_D
  • 201,275
  • 16
  • 291
  • 322
1

The approach in the OP seems to overthink the problem. The following code does exactly what the OP code would probably do if it was valid:

Group group = new Group(new Button("Hello"));

Of course it's going to be difficult to do anything with that button since there's no action associated with it. The straight-ahead approach is to just instantiate it as a variable, add an action and then put it in the new Group:

 Button button = new Button("Hello");
 button.setOnAction(evt -> System.out.println("hello"));
 Group group = new Group(button);

If you are going to set up a lot of buttons with nothing more than a label and an action, then it makes sense to set up a "builder" method to make it easier. Then you can in-line the method call when setting up the Group:

private Node createButton(String label, EventHandler<ActionEvent> handler) {
    Button result = new Button(label);
    result.setOnAction(handler);
    return result;
}

And call it like so:

Group group = new Group(createButton("Hello", evt -> System.out.println("Hello")));

Of course, if you are going to do this a lot, then it makes sense to create a static library of convenience methods that will do this sort of thing. Then you can inline huge amounts of code and stick to the DRY principle:

 Group group = new Group(TextWidgets.headingText("A Heading"),
                         TextWidgets.boundDataText(stringProperty),
                         createButton("Hello", evt -> System.out.println("Hello")));

The JavaFX controls are just Java classes like any others, and there's really nothing special about creating them and calling their methods to configure them and connect them together.

DaveB
  • 1,836
  • 1
  • 15
  • 13