kordamp / ikonli

Icon packs for Java applications
http://kordamp.org/ikonli/
Apache License 2.0
500 stars 50 forks source link

Binding icon size results in exception #132

Closed lanthale closed 3 years ago

lanthale commented 3 years ago

I try to bind the iconsize to the parent (stackpane) height but getting always the following exception: java.lang.RuntimeException: FontIcon.iconSize : A bound value cannot be set

The binding itself works perfectly but the exception is thrown, also when I call beforehand unbind on the iconsizeproperty. I do not know why the value is already bound. Setting in the constructor the iconsize works without any issues but binding throws the exception.

The binding is taking place in the constructor of that class.

Here is the code from the constructor: dummyIcon = new FontIcon("fa-file-movie-o"); dummyIcon.setIconSize(40); dummyIcon.iconSizeProperty().unbind(); dummyIcon.iconSizeProperty().bind(rootPane.heightProperty().subtract(10));

aalmiray commented 3 years ago

As far as I can see there's no internal binding code to be found in org.kordamp.ikonli.javafx.FontIcon. Are you sure there's no other library/setting getting in the way?

Also, if creating a binding is a problem you could register a ChangeListener instead.

lanthale commented 3 years ago

I have found the issue. If I call setIconSize(40) (must be different than 8) the issue is there. If I do not set the iconsize before all is working.

The following code throws the exception: dummyIcon = new FontIcon("fa-file-movie-o"); dummyIcon.setIconSize(40); dummyIcon.iconSizeProperty().bind(rootPane.heightProperty().subtract(10));

And now this code is working: dummyIcon = new FontIcon("fa-file-movie-o"); dummyIcon.iconSizeProperty().bind(rootPane.heightProperty().subtract(10));

That means the method setIconSize is binding a value somehow.

aalmiray commented 3 years ago

Well the method is defined as

https://github.com/kordamp/ikonli/blob/master/core/ikonli-javafx/src/main/java/org/kordamp/ikonli/javafx/FontIcon.java#L190-L195

While the property is created at

https://github.com/kordamp/ikonli/blob/master/core/ikonli-javafx/src/main/java/org/kordamp/ikonli/javafx/FontIcon.java#L105-L130

lanthale commented 3 years ago

Thank you. So this could not be the root cause. I am searching further where the issue comes from. I am using the controlsfx GridView which uses VirtualFlow.

Here is the complete stackflow: ` Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: FontIcon.iconSize : A bound value cannot be set. at javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:144) at javafx.graphics/javafx.css.StyleableIntegerProperty.set(StyleableIntegerProperty.java:82) at org.kordamp.ikonli.javafx@12.0.1-SNAPSHOT/org.kordamp.ikonli.javafx.FontIcon.setIconSize(FontIcon.java:194) at org.kordamp.ikonli.javafx@12.0.1-SNAPSHOT/org.kordamp.ikonli.javafx.FontIcon.lambda$new$0(FontIcon.java:61) at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181) 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.graphics/javafx.css.StyleableObjectProperty.applyStyle(StyleableObjectProperty.java:68) at javafx.graphics/javafx.scene.CssStyleHelper.transitionToState(CssStyleHelper.java:790) at javafx.graphics/javafx.scene.Node.doProcessCSS(Node.java:9665) at javafx.graphics/javafx.scene.Node$1.doProcessCSS(Node.java:481) at javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSSImpl(NodeHelper.java:192) 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:900) 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.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:900) 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.Node.processCSS(Node.java:9547) at javafx.graphics/javafx.scene.Node.applyCss(Node.java:9634) at javafx.controls/javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1743) at javafx.controls/javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:2023) at javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1244) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214) at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576) at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2476) at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:413) at java.base/java.security.AccessController.doPrivileged(AccessController.java:391) at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:412) at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:439) 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)

`

aalmiray commented 3 years ago

I think I have an idea of what may be happening. The call to setIconSize() changes the font, which in turn triggers setIconSize() again due to the listener attached to the font property on line 61.

lanthale commented 3 years ago

I did the following test: Execute dummyIcon.iconSizeProperty().bind(rootPane.heightProperty().subtract(10)); -> Results in Exception

Execute dummyIcon.iconSizeProperty().bind(rootPane.heightProperty()); -> No Exception

That means that the subtract method is causing the issue somehow.

aalmiray commented 3 years ago

It might be a timing issue related to the listener, as if the binding were to be in place before the listener triggers.

lanthale commented 3 years ago

Yes I think as well that this is the root cause.

lanthale commented 3 years ago

As a workaround I am using a PauseTransition with 100ms before doing the binding. Than the exception is gone and it proves your code change to be the root cause.