JFXtras / jfxtras-styles

Java, JavaFX themes or look and feels. Currently contains JMetro theme.
https://pixelduke.com/java-javafx-theme-jmetro/
642 stars 144 forks source link

class impl.jfxtras.styles.jmetro.ProgressBarSkin cannot be cast to class javafx.scene.control.skin.ProgressBarSkin #200

Closed iazarny closed 2 years ago

iazarny commented 3 years ago

Javafx version 11, 11.0.2 Jmetro version 11.6.14 OS Win I've the following exception on app start and during progress bar updating . App is working, but a lot of error messages in the console.

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class impl.jfxtras.styles.jmetro.ProgressBarSkin cannot be cast to class javafx.scene.control.skin.ProgressBarSkin (impl.jfxtras.styles.jmetro.ProgressBarSkin is in module org.jfxtras.styles.jmetro of loader 'app'; javafx.scene.control.skin.ProgressBarSkin is in module javafx.controls of loader 'app') at javafx.controls/javafx.scene.control.skin.ProgressBarSkin$StyleableProperties$2.isSettable(ProgressBarSkin.java:420) at javafx.controls/javafx.scene.control.skin.ProgressBarSkin$StyleableProperties$2.isSettable(ProgressBarSkin.java:416) at javafx.graphics/javafx.scene.CssStyleHelper.transitionToState(CssStyleHelper.java:666) at javafx.graphics/javafx.scene.Node.doProcessCSS(Node.java:9647) at javafx.graphics/javafx.scene.Node.access$900(Node.java:398) at javafx.graphics/javafx.scene.Node$1.doProcessCSS(Node.java:471) 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:1366) at javafx.graphics/javafx.scene.Parent.access$400(Parent.java:79) 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.access$000(Control.java:83) 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:1397) at javafx.graphics/javafx.scene.Parent.access$400(Parent.java:79) 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:1397) at javafx.graphics/javafx.scene.Parent.access$400(Parent.java:79) 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.access$000(Control.java:83) 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:1397) at javafx.graphics/javafx.scene.Parent.access$400(Parent.java:79) 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:9529) at javafx.graphics/javafx.scene.Scene.doCSSPass(Scene.java:569) at javafx.graphics/javafx.scene.Scene.access$3400(Scene.java:172) at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2477) 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:519) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320) 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) Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at javafx.controls/javafx.scene.control.skin.ProgressBarSkin.updateProgress(ProgressBarSkin.java:376) at javafx.controls/javafx.scene.control.skin.ProgressBarSkin.lambda$new$0(ProgressBarSkin.java:101) 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.ReadOnlyDoublePropertyBase.fireValueChangedEvent(ReadOnlyDoublePropertyBase.java:72) at javafx.base/javafx.beans.property.ReadOnlyDoubleWrapper.fireValueChangedEvent(ReadOnlyDoubleWrapper.java:103) at javafx.base/javafx.beans.property.DoublePropertyBase.markInvalid(DoublePropertyBase.java:114) at javafx.base/javafx.beans.property.DoublePropertyBase.set(DoublePropertyBase.java:148) at javafx.graphics/javafx.scene.layout.Region.setWidth(Region.java:986) at javafx.graphics/javafx.scene.layout.Region.resize(Region.java:1488) at javafx.graphics/javafx.scene.layout.Region.layoutInArea(Region.java:2548) at javafx.graphics/javafx.scene.layout.Region.layoutInArea(Region.java:2459) at javafx.graphics/javafx.scene.layout.HBox.layoutChildren(HBox.java:647) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1204) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1211) at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1211) at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576) at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2482) 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:519) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320) 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)

dukke commented 3 years ago

Hi,

Can you provide a small test app that shows the bug happening? Without it I can't really say what's going on and whether the problem is really a JMetro thing..

Thanks,

iazarny commented 3 years ago

App is attached. In short - fxml has a progress bar, and this is enough. jmetrobug.zip

dchuyko commented 3 years ago

+1. Not OS specific (e.g. happens on Linux).

dukke commented 2 years ago

@iazarny @dchuyko Truly sorry for the wait I've been very busy with my day to day work.

So after debugging your attached example app I've nailed it down to a bug in JavaFX itself (not JMetro).

The solution is to instantiate an instance of JMetro and set its scene property before you show the stage. It needs to be like this so that the default JavaFX ProgressBar Skins never get set on the controls (this is the problem there is a bug in the default JavaFX ProgressBar skin class).

The problem is that the default javafx Progresssar skin (javafx.scene.control.skin.ProgressBarSkin) doesn't clean up its listeners properly.

In the constructor of ProgressBarSkin it adds a listener to the width property of the control:

control.widthProperty().addListener(observable -> updateProgress());

Since this is an anonymous listener it is never removed when the skin gets disposed. After JMetro switches the skins of the ProgressBars with its own skins, the previous default ProgressBar skins will have a null control. Since the listener on the ProgressBar control I mentioned never gets removed, it will still be called, but since the control in the javafx ProgressBarSkin class is null it will give a NPE here (method updateProgress() of ProgressBarSkin):

ProgressIndicator control = getSkinnable();
// RT-33789: if the ProgressBar was indeterminate and still is indeterminate, don't update the bar width
final boolean isIndeterminate = control.isIndeterminate();

I believe this probably has been fixed in the latest versions of JavaFX. Though, if you guys do things like I mentioned you also won't have this problem.