Wow – this release of ControlsFX is a big one in all respects! It took just shy of three months, consists of nearly 500 changesets, has been translated into 17 languages, and includes a huge number of bug fixes and new features. This is going to be a long post, so strap yourselves in and please read to the very end – this release has some important changes!
This release also continues in the long tradition of being a real team effort. ControlsFX wouldn’t be where it is today without the hard work of the following contributors: Eugene Ryzhikov, Samir Hadzic, Gabriel Féron, Carolina Veiga, Anirvan Sarkar, IsNull, Artur Biesiadowski, Yair Oren, Davide Nabais, Tom Eugelink, Michał Skowroński, Uwe Sander, Laurent Gebus, Geoffrey Capper, Romain Moreau, Mario Voigt, Ruben Paz, Jonathan Millman, Chen Gaofeng, Ladislav Török, Tiziano Lattisi, Victor Alfonso Pineda Orozco, Daniel Rodrigues, Avramucz István, Sriram Raghuraman, Dirk Lemmermann, Florian Brunner, and Christian Michelsen. Apologies if I missed anyone! As always, if you see these people walking down the street, give them a high-five or a knowing wink, as in to say “You’re a cool person – I appreciate your hard work”.
With that out of the way, lets dive in.
Important Release Note Regarding JavaFX 8u20
Everyone should upgrade to ControlsFX 8.0.6, but especially so if you are running JavaFX 8u20 on your machine. This is because ControlsFX 8.0.6 is the first release to support 8u20. You may be asking yourself why this is necessary – the answer is that ControlsFX uses internal JavaFX API, and this changed between JavaFX 8 and JavaFX 8u20. This is entirely our doing, so is no reflection on JavaFX itself. To support 8u20, we therefore are forced to release two separate releases: ControlsFX 8.0.6 for JavaFX 8.0, and ControlsFX 8.0.6_20 for JavaFX 8u20. I apologise for the extra hassle, but hey, at least ControlsFX works on both, right? 🙂
New Features
I should start by saying that this release was largely about consolidating what we had, so most of our focus has been on improving the quality of the release, and slowing down the introduction of new features. This approach will continue in future releases, as I don’t want to let the quality of any release fall below a (very high) threshold. This release was largely focused on decoration and validation. We already have plans for future releases – if you want to know more, it is a good idea to join our google group.
Decoration framework
ControlsFX 8.0.6 introduces a brand new (and at this stage relatively simplistic) decoration framework, to allow for developers to apply decorations to nodes on screen. For example, you may want to show graphics in the corner of your nodes, or add a styleclass in certain circumstances. The decoration framework makes this kind of action trivial. However, to be fair, the decoration framework was primarily developed to be the visual feedback mechanism for a validation framework, and we have one of those in ControlsFX 8.0.6 too (read down a bit further to see screenshots of it in action!).
SnapshotView
The SnapshotView is a control that allows for users to draw a bounding box inside a scenegraph (or typically in an ImageView). This bounding box represents the dimensions of their selection, and from which an image can be created of the selected area. This is another of those controls that is easier to describe with an image, so, see below! 🙂
Translations
We did a big push in ControlsFX 8.0.6 to externalise all translatable strings, and to get the community to help translate these strings into their local languages. I am so pleased to say that the community did an excellent job, resulting in ControlsFX 8.0.6 being translated into 17 languages! Hopefully in future versions we can take that number even higher, but for now we really do have an excellent amount of language coverage.
Validation framework
As mentioned above, we introduced a decoration framework in 8.0.6, primarily to enable the validation framework. The validation framework helps developers to validate user input and assists with reporting errors and warnings. It is designed to be lightweight but extensible, and will grow over time as developers suggest desired functionality (we are definitely open to suggestions!).
Other miscellaneous improvements
We can’t list everything (that’s what the hg changelog is for!), but here are some other highlights:
- The SpreadsheetView continues to be improved – performance is better, functionality is greater, and API is becoming more polished.
- It is now possible to specify the effect to display when a lightweight dialog is shown (rather than the default gray background).
- The FXSampler project (which is a standalone project that you can use to demonstrate your own JavaFX stuff!) now has support for custom welcome pages. Very cool!
- The login dialog shakes (almost mockingly) when you type in the wrong username / password combination.
- The PopOver control got some useful bug fixes and additional API for hiding PopOver.
Breaking Changes
There is always a tension when working on API between retaining a stable API and continuously improving the API. Believe me, I’ve heard all arguments in my work on JavaFX UI controls! Unlike JavaFX with ControlsFX we are a little more flexible with our backwards compatibility requirements. In other words, I am more than happy to break API to get a better API. This release is by far the biggest release for breaking API, so I want to spend a few moments outlining the major changes, and what you need to do to upgrade to ControlsFX 8.0.6.
Action extends EventHandler<ActionEvent>
Previously the Action interface had an execute(ActionEvent) method, but it seemed pointless to roll our own API when, by extending EventHandler<ActionEvent>, we could directly install an action into, say, the Button.setOnAction(EventHandler<ActionEvent>) method. Unfortunately, EventHandler has a handle(ActionEvent) method, so this means that in all cases where you had Action code, you simply need to rename your execute method to handle.
Dialogs now return Optional
With Java 8 introducing the Optional class, we have updated some of the Dialogs API to return Optional, rather than the object directly. This means that previously where there was code that looked like the following:
String response = Dialogs.create() .title("Name Check") .masthead("Please type in your name") .message("What is your name?") .showTextInput(); if (response != null) { System.out.println(response); }
You now instead need to do the following:
Optional<String> response = Dialogs.create() .title("Name Check") .masthead("Please type in your name") .message("What is your name?") .showTextInput(); response.ifPresent(name -> System.out.println(name));
In other words, code that previously checked for null will now no longer work, as the returned Optional will never be null! You need to instead operate on the Optional instead, as shown above.
Getting ControlsFX
As per usual, more details about getting and using ControlsFX can be found on the ControlsFX website. You can also read through a high-level summary of all the features in this release, and peruse the JavaDocs (where we put the bulk of our documentation) if you want the gritty details.
From all the ControlsFX contributors, we hope you enjoy this release, and we hope that you may consider supporting the project in the future!
Under the section titled “Dialogs now return optional” I think you have a code mistake. In the first example you code “String name = …” and then ask the question “if (response != null)”. I think the String variable should be called “response”.
Thanks – editing of code in a blog post never turns out well! 🙂
how to use spreadsheetView with SceneBuilder 2.0?
Janerson, please ask this question in the ControlsFX-dev group, here: http://groups.controlsfx.org
wonderful updates i can make a pivot table based on spreadsheetview, thanks!great job!
I hope you plan to contribute your work back to the ControlsFX project! 🙂
ok, i’ll commit my work once i complete it. It’ll be great honor to be adopted.
where are the links to javafx in oracle website?, all links redirects to java jdk and jre only
Another great update! Bug report though: trying to create a notification when all windows (stages) are hidden (and platform.setImplicitExit is set to false ofc) will give an error about a null owner window. However, for many applications, this is an important feature to have – they should be able to run in the background (mines in notification pane) and still be able to show notifications as they come up. Any chance you could fix this?
Thankyou for such a great release!
Yes, great release. Unfortunately, I cannot set a cursor on the SnapshotView. setCurosr() has no effect 🙁
controlsfx-samples-8.0.6.jar throws a NullPointer if you try out the “SpreadsheetView”.
The Exception:
Exception in thread “JavaFX Application Thread” java.lang.NullPointerException:
Input stream must not be null
at javafx.scene.image.Image.validateInputStream(Unknown Source)
at javafx.scene.image.Image.(Unknown Source)
at org.controlsfx.samples.HelloSpreadsheetView.getLogos(HelloSpreadsheet
View.java:424)
at org.controlsfx.samples.HelloSpreadsheetView.buildGrid(HelloSpreadshee
tView.java:586)
at org.controlsfx.samples.HelloSpreadsheetView.getPanel(HelloSpreadsheet
View.java:122)
…
Apparently a logo is missing, even though all the pictures are in the JAR.
PS: I can post the hole exception if you want.
Please file issues here: http://issues.controlsfx.org – thanks!
Hey there,
i use the Validation framework. Here my Code.
@FXML
void abrufAPKAction(ActionEvent event) {
abrufAPKboolean = abrufAPK.isSelected();
if (abrufAPKboolean == true) {
abrufAPKSQLCode.setDisable(false);
abrufAPKSQLCode.setOpacity(1.0);
abrufAPKText.setOpacity(1.0);
validationSupport.registerValidator(abrufAPKSQLCode, (Control c, String newValue) ->
ValidationResult.fromErrorIf(abrufAPKSQLCode, "Bitte ausfüllen. Max. Zeichen 495.", (newValue.trim().length() > 495) || (newValue.trim().length()
ValidationResult.fromErrorIf(abrufAPKSQLCode, "Max. Zeichen 495.", newValue.trim().length() > 495));
}
}
I want when the Checkbok is true that the validation support is active . If the checkbox is false then no more. Is this possible .
Thx
I’m sorry.
This is the right Code.
@FXML
void abrufAPKAction(ActionEvent event) {
abrufAPKboolean = abrufAPK.isSelected();
if (abrufAPKboolean == true) {
abrufAPKSQLCode.setDisable(false);
abrufAPKSQLCode.setOpacity(1.0);
abrufAPKText.setOpacity(1.0);
validationSupport.registerValidator(abrufAPKSQLCode, (Control c, String newValue) ->
ValidationResult.fromErrorIf(abrufAPKSQLCode, “Bitte ausfüllen. Max. Zeichen 495.”, (newValue.trim().length() > 495) || (newValue.trim().length() < 1)));
} else {
abrufAPKSQLCode.setDisable(true);
abrufAPKSQLCode.setText(null);
abrufAPKSQLCode.setOpacity(0.5);
abrufAPKText.setOpacity(0.5);
}
}