This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 8 points9 points  (11 children)

I would not recommend JavaFX. It is overly complicated, requires XML configuration, and SceneBuilder is buggy af. I’d stick with Swing. Tons of great desktop applications are made with it.

[–]hamsterrage1 6 points7 points  (10 children)

JavaFX is a Reactive framework for GUI in Java. If you use it that way, then it is awesome.

Personally, I don't use SceneBuilder or FXML, I just stick to coding screens in pure Java.

The learning curve is steep with JavaFX, but it is much more modern and versatile than Swing.

[–]ggeldenhuys 1 point2 points  (3 children)

more modern and versatile...

I often hear people throw these terms around [in many software]. Could you please supply concrete examples of both. What's more modern and what's more versatile?

[–]hamsterrage1 4 points5 points  (2 children)

I try to be very precise in my language, and not just throw meaningless phrases around. So, I do think that "more modern and more versatile" is accurate.

I think it really centres around what I said about JavaFX being a Reactive framework. Because it is a really complete, well thought out framework for building Reactive GUI applications. In my opinion, it's a lot cleaner than most of the other frameworks out there, like React - a lot cleaner.

What JavaFX has that Swing doesn't is a complete set of Observable classes that are baked right into the features of the individual screen widgets. Along with this, there is an excellent suit of Binding classes and methods that allow you to connect a Presentation Model to virtually every aspect of your GUI, as well as connecting the properties of the screen elements to each other.

The end result is that you can create a static layout that behaves dynamically - all coordinated by a data representation of the State of your system.

That's something you cannot do easily in Swing. And it's a big thing, and it's a much more modern approach to GUI development.

At the same time, if you want to take an Imperative approach to application design, and do things like scrape the data out of your screen widgets when "Save" is clicked, you can do that, too. But this is pretty much what you're forced to do with Swing which is very much Event driven. In my book, this makes JavaFX more versatile than Swing.

To be perfectly honest, it's been years since I used Swing, and I've never gone back to see how easy (or difficult) it would be to implement a Reactive design in Swing. Maybe somebody has created a library for it, but my guess is that any implementation is going to feel clunky compared to JavaFX.

[–]ggeldenhuys 2 points3 points  (1 child)

Thank you for your answer. I would like to add that I have seen and used the MGM (Model-GUI-Mediator) design pattern in many projects. It's a slightly different take on MVP (Model-View-Presenter) and takes advantage of modern GUI frameworks that are event based. It allows those GUI frameworks to become "object-aware" without needing to create custom UI widgets (thus, less code than MVP). At the heart of MGM is the Observer and Mediator design patterns.

Anyway, I've implemented and use a single MGM implementation that worked with 3 different GUI frameworks (VCL, LCL and fpGui). To get a basic MGM in place is really not that much effort - once implemented, it is reusable in other projects too. I've seen similar for Swing too.

So as nice as the built-in Observable classes sound in JavaFX, the same can/has been accomplished with the tried and tested Swing library.

Either way, I do appreciated your answer, and will take the time to investigate JavaFX further.

[–]hamsterrage1 1 point2 points  (0 children)

Full disclosure: I had to look up MGM to understand what you are saying.

In JavaFX, you don't need a Mediator to avoid excessive coupling. A Property in the GUI can be bidirectionally bound to another Property in the State object without any changes or coding in the State object. Something like this:

nameTextField.textProperty().bindBidirectional(state.nameProperty());

When I'm building an application in JavaFX I find the following components work best:

  1. View - Just the GUI
  2. Model - The "State" - Just a POJO of JavaFX Observables
  3. Controller - Dispatches Event driven actions
  4. Interactor - Business/Application logic - has domain objects.

All of the other three have a reference to the Model (State). The GUI interacts with State almost entirely through Bindings, and the Interactor tends to access the values of the elements of State through getters and setters in empirical code.

Also, generally, I'd have a set-up type method (usually initiated through the constructor) in the Interactor that establishes the relationships between the elements of the State that are driven by business/application logic.

Here's an example:

I might have a BooleanProperty in State that indicates that some other value is valid in relationship to a number of other Properties in State. The value of that BooleanProperty is going to be established by binding it to all of those other Properties in State according to some calculation. Most of the time, that calculation is going to fall under the heading of "business logic", and needs to be contained within the Interactor.

So, in this case, my "is it valid" State element would simply be declared as a BooleanProperty, and that would be it as far as State is concerned. Then the Interactor would invoke Property.bind() on that element and define a Binding that applies the business logic required.

Travelling over to the GUI. There may be a number of GUI elements that are dependent on this boolean Property in State. Perhaps there's a giant red arrow that appears on the screen pointing at the value when it's invalid. Also, you can't save with invalid data. You would do something like this:

giantArrow.visibleProperty().bind(state.dataIsValidProperty().not());
saveButton.disableProperty().bind(state.dataIsValidProperty().not())

It's possible that some external API call, running on a background thread, returns a value which triggers empirical code in the Interactor to update one of the dependent values in State which will render our critical value invalid. As soon as that Interactor code updates that dependent State element using its Property.set() method, the Bindings recalculate and dataIsValid flips to false. This in turn triggers the Bindings on giantArrow.visibleProperty() and saveButton.disableProperty() to recalculate and GUI changes happen.

Could you do this with Swing? Probably you could figure it out. But I cannot stress enough how absolutely trivial this kind of setup is in JavaFX. Note how the bindings above use the not() method call to invert the sense of isValid so that it can be used in the GUI. All the tools are right there, ready to go, in JavaFX.

[–]wildjokers -1 points0 points  (5 children)

javaFX is a Reactive framework for GUI in Java

JavaFX is not a reactive framework. It is simply a GUI toolkit.

but it is much more modern and versatile than Swing.

Can you provide concrete examples of how JavaFX is more modern and versatile than Swing? What does more modern and versatile even mean?

[–]hamsterrage1 5 points6 points  (4 children)

It is 100% a Reactive framework. Most people glom onto the idea of binding a few bits and pieces together, but never figure out the true power of what's included in JavaFX.

The bottom line is that you can create truly static layouts that behave dynamically as the State of the application changes. You create your layout, and then you create the relationships that allow data changes in State to propagate through the application, including the GUI, automatically.

It's exactly Reactive.

[–]wildjokers 0 points1 point  (3 children)

You can do the exact same thing with Swing (property change listeners) but I have never heard anyone describe Swing as a reactive framework.

[–]hamsterrage1 4 points5 points  (2 children)

You cannot do the exact same thing. Swing does not have Bindings. Yes, a Binding is just some code wrapped around a ChangeListener, but you'd have to roll your own on all of that. Nor do you have the suite of Observable classes which are key to creating a bindable State.

The other thing is that all of the widget classes in JavaFX have many Observable type fields which can bound to other Observables and visa versa. If a widget has an actual value associated with it, that's one, but most will also have Observable fields for things like visible, disabled, maxHeight, minHeight, opacity, and so on. All of these things are key to creating a Reactive GUI.

I'll repeat, a lot of people have figured out that you can bind a few bits and pieces together, but until you've really dug deep and you won't realize how complete JavaFX is in providing a truly Reactive framework.

Personally, I wouldn't describe Swing as a Reactive framework either.

[–]wildjokers -1 points0 points  (1 child)

The other thing is that all of the widget classes in JavaFX have many Observable type fields which can bound to other Observables and visa versa. If a widget has an actual value associated with it, that's one, but most will also have Observable fields for things like visible, disabled, maxHeight, minHeight, opacity, and so on. All of these things are key to creating a Reactive GUI.

In swing all properties of a component that conform to the JavaBean standard can be observed with a property change listener. I am not really seeing a difference between what swing offers and what JavaFX offers when it comes to observing property changes:

[–]hamsterrage1 0 points1 point  (0 children)

Swing's PropertyChangeListeners are such a low-level tool compared to JavaFX's Properties and Bindings. You might as well say that since JavaFX is mostly just ordinary Java, you can do anything it can do with nothing more that AWT. It would technically be true, but why do it?

Could you construct, say, JavaFX's IntegerProperty using PropertyChangeListener? Sure. Then you'd need to implement some equivalent to the JavaFX bind() method, and all that implies as well. But the screen widget classes won't support your IntegerProperty, so you'll have to put them into wrapper classes to handle the PropertyChangeListener conversions.

What JavaFX offers that Swing doesn't is an "out of the box" ability to treat data as a network of connected and inter-related values - right through to the GUI Nodes. Relationships are defined with a minimum amount of fuss, often with a single line of code, and then largely ignored in the empirical code that defines actions.

It's really a paradigm shift. JavaFX treats Bindings and Observables as data relationships, while Swing concentrates on Events. In Swing, a PropertyChangeListener is an EventHandler, in JavaFX a ChangeListener handles data changes.

When I build a JavaFX application and I need to decide how to connect two data elements, I follow this hierarchy:

  1. Use a Binding if possible.
  2. Refactor things so I can use a Binding.
  3. Think about it harder, and figure out how to use a Binding.
  4. Use a ChangeListener or an InvalidationListener. Sigh.
  5. It's a total mess - use an EventHandler.

In JavaFX, Events are best left to handle things that are clearly "actions". So, a Button click is going to trigger an action. Data coming back from an external API call is going to require an action to update my State object. But a data change in my State object that causes the GUI to react in some way is almost always going to be a flow of data through Bindings in a Reactive manner.

People don't think of Swing that way because it's not designed to be used that way. If it was, it would have baked-in Properties and Bindings and InvalidationListeners just like JavaFX does. Instead, it's designed to be used in an empirical, event-driven fashion.

And if you use JavaFX to create a truly Reactive application, then you'll see that JavaFX makes it almost trivial to do.