Hi again! This time a new version that is, as promised, JavaFX 11 compatible.
Keep on reading for details.
JMetro 8.5.7 and 11.5.7 versions
JMetro code has been divided into 2 branches. The master branch holds the Java 8 compatible JMetro version and “11” branch has the Java 11 compatible version. Versions starting with “11.” will be for Java 11 and versions starting with “8.” will for Java 8.
“11” branch is being tested against JavaFX11 but probably should work fine with JavaFX 9 up to the upcoming JavaFX 13.
All the CSS from previous JMetro versions could be used with JavaFX11 the difference here is that now the new skins referenced through CSS also work.
The difficulty here with the migration is that the code has changed significantly from JavaFX8 to JavaFX9 with control skins becoming public and their code changing. Also the introduction of modules and its use in JavaFX9+ framework code, made accessing internal classes used by skins, like “Behavior” classes, impossible (not impossible under some circumstances, but still undesirable).
All skins have been converted. They are:
- Button Skin
Adds a spring button press animation on Toggle Buttons and regular Buttons: https://pixelduke.com/2018/08/27/fluent-design-button-toggle-button-tooltip/
- TextField Skin and PasswordField Skin
Adds a button to the right of Textfield that allows you to clear the text, and for PasswordField the button will allow you to see the password in plain text: https://pixelduke.com/2019/01/20/jmetro-version-5-2-released/ , https://pixelduke.com/2018/09/09/fluent-design-style-text-field-and-password-field-for-java-javafx/
- ProgressBar Skin
Sets an appearance for the indeterminate ProgressBar, equal to the Fluent Design specification indeterminate ProgressBar: https://pixelduke.com/2018/09/30/fluent-design-style-progress-bar-for-java-javafx/
- Slider Skin
Adds a fill to the Slider. Something that I think is a glaring omission right now in the JavaFX Slider. And adds a popup that shows up to tell the user the exact value that’s being set on the Slider while the thumb is being dragged: https://pixelduke.com/2018/08/19/fluent-design-slider-java-javafx/
- Toggle Switch Skin
A new Skin
for the Toggle Switch control I’ve created for ControlsFX. It adds some features and fixes: https://pixelduke.com/2018/08/12/fluent-design-toggle-switch-java-javafx/
New features in 8.5.7 and 11.5.7
For developers familiar with the previous JMetro versions, the API has changed.
The constructor for the JMetro
class now takes in a Scene
and a Style
or a Parent
and a Style
.
Then the following properties were added:
- Style
Either DARK
or LIGHT
style appearance.
- Scene
The Scene
that will have the JMetro theme applied.
- Parent
The Parent
that will have the JMetro theme applied. If this property is set and a Scene
has also been set previously, changes to the JMetro instance will start to apply to the new specified Parent
and not the Scene
. In case the Scene
is set after a Parent
has been set the reverse will happen.
- AutomaticallyColorPanes
If true, all Panes
(e.g. BorderPane, AnchorPane, StackPane, Pane
, etc) will automatically have their background color set. If the style is DARK
the background will be dark (like black), if the style is LIGHT
the background will be light (like white). This has the disadvantage that if you have custom controls that have Panes as intermediate children, you’ll usually need to redefine their background to transparent or else you might get whitish/blackish background patches in your custom controls. Alternatively, if this property is set to false (the default), you can add the style class .background
to the Panes that are supposed to be in the background of your application. They will then automatically change their background color according to the Style
property value.
- getOverridingStylesheets
This is actually more of an ObservableList
that you can add stylesheets to. This stylesheets will be added after the stylesheets that make up the JMetro theme definition. This means that the stylesheets added to this list will override the definitions set by the JMetro theme in case their specificity is the same or higher. As such, this is a good place to redefine and add your own custom styles that override the JMetro ones.
Other changes
Other than the changes mentioned above. A couple more fixes have been made to existing JMetro styles. All JMetro samples have been migrated to JavaFX11 in the “11” branch. Finally the code has been cleaned and things like the CSS code that still existed for JavaFX2 has been removed.
Wrapping up
As promised a JavaFX9+ version of JMetro is now also available . I was trying to post-pone this as I still have Java8 clients that happen to be using JMetro and maintaining 2 versions can be a pain. As such the Java 8 version in the master branch will still be maintained for the time being.
The API has also been cleaned and I think now it is cleaner and better. New properties have also been added to the JMetro
class that allow to further customize JMetro.
Hi,
Using JavaFX on Java 14. Trying to create a TextField:
java.lang.NullPointerException
at javafx.controls/javafx.scene.control.skin.TextFieldSkin.lambda$new$5(TextFieldSkin.java:270)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:348)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.graphics/javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
at javafx.controls/javafx.scene.control.TextInputControl$3.set(TextInputControl.java:234)
at javafx.controls/javafx.scene.control.TextInputControl$3.set(TextInputControl.java:203)
at javafx.graphics/javafx.css.StyleableObjectProperty.applyStyle(StyleableObjectProperty.java:68)
at javafx.controls/javafx.scene.control.TextInputControl$3.applyStyle(TextInputControl.java:218)
at javafx.controls/javafx.scene.control.TextInputControl$3.applyStyle(TextInputControl.java:203)
at javafx.graphics/javafx.scene.CssStyleHelper.transitionToState(CssStyleHelper.java:787)
at javafx.graphics/javafx.scene.Node.doProcessCSS(Node.java:9660)
at javafx.graphics/javafx.scene.Node$1.doProcessCSS(Node.java:472)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSSImpl(NodeHelper.java:192)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.superProcessCSSImpl(ParentHelper.java:93)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.superProcessCSS(ParentHelper.java:63)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1369)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
at javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:886)
at javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
at javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:886)
at javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
at javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:886)
at javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
at javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:886)
at javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
at javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:886)
at javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Parent.doProcessCSS(Parent.java:1400)
at javafx.graphics/javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
at javafx.graphics/javafx.scene.Node.processCSS(Node.java:9542)
at javafx.graphics/javafx.scene.Scene.doCSSPass(Scene.java:569)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2505)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Thanks for the fix4
Hi David,
1- Please register the issue in the issue tracker: https://github.com/JFXtras/jfxtras-styles/issues
2- Attach a small test app that I can easily run and that illustrates the bug.
3- Specify steps to reproduce the bug.
4- State the Java, JavaFX and JMetro version being used.
Thanks!
Hi!
I made a minimal example – bottom line: while using JMetro alone the problem is not reproducable.
The problem apper if used together with TornadoFX + Kotlin.
The problem can be worked around, if the application is started the official way, not the TornadoFX way. After this I am not so confident, that the problem is coming from JMetro, however, TornadoFX is a quite popular library, so it may worth it to investigate.
Should I submit the issue still?
David
Thanks for clearing things up, David.
I have come up with workarounds before for TornadoFX users who come up with bugs that originated in TornadoFX. However I don’t feel this is the way to go, if TornadoFX is having issues somehow (or any other library) then it should be TornadoFX that fixes it. It is the root of the bug.
It’s not sustainable to have all the other libraries come up with workarounds for a specific bug in one library. Rather it is much more reasonable to have that library, that has the bug, fix it.
Having said that, I think the answer would be to file the bug in the TornadoFX issue tracker.
Thanks,