Closed frankb33 closed 6 years ago
Sorry, for wasting your time. I haven't touched this code for a VERY long time. SwingUtilities.updateComponentTreeUI on all open dialogs fixed the issue. A classical RTFM :(
SubstanceCortex.GlobalScope.setSkin() in the upcoming 8.0 (or SubstanceLookAndFeel.setSkin in pre-8.0) will call SwingUtilities.updateComponentTreeUI on all application windows.
Hi Kiril,
SubstanceCortex.GlobalScope.setSkin() in the upcoming 8.0 (or SubstanceLookAndFeel.setSkin in pre-8.0) will call SwingUtilities.updateComponentTreeUI on all application windows.
Thanks for your quick response. I found another issue with secondary menus (although they are not shown at the time of the LaF-switch?? And difficult to reproduce. I have to switch between the themes at least a dozen times or so), so I ask the user for a application restart when switching between Substance and Synthetica themes (in one “family” all it smooth) as I did it already between decorated and undecorated windows (I use substance only without native decoration). It’s just a little inconvenience for the user and IMHO far better than an occasionally malfunction.
BTW I’m very glad that there is support for Swing and in your case really excellent. I have a spare time project for quite some time and it is simply too much work to switch to JavaFX (even if the migration path is less difficult) and I love polished surfaces :)
Best Frank
P.S. If you enjoy playing Backgammon I send you a free license.
Is it the same stack trace with secondary-level menus?
In general, since I came back to Substance, my line of thinking is that as an application developer it is much better for the visual polish and consistency of the app to choose one look-and-feel and one skin in that look-and-feel, and integrate tightly with that specific appearance.
You can see that in the list of customizations that Substance supports with SubstanceCortex, that Synthetica supports with their APIs and that WebLaf does with theirs.
I'm not saying that Substance specifically should not fully support switching to and from other look-and-feels. It's just that supporting that at the application level (some preference or switch) means that you are losing out at the additional features that you can get from your look-and-feel of choice.
Having said that, if you have a small standalone app that shows the issue you're experiencing with menus under the latest versions of Substance and Synthetica, re-open this and I'll take a look.
(accidentally clicked "Comment" in the middle of replying. Read the previous one fully in case you have only seen only that early part of it)
I appended the trace (just in case). I just read a bit in the Synthetica documentation. They recommend to restart the application, when switching to a non Synthetica LaF, so I guess thats the safe choice.
I provide so many boards with different styles (see here http://www.bgblitz.com/themes.html or here http://www.dcbackgammon.com) that switching the LaF for a matching LaF is the cream of the crop :) The fun fact: most users stick with the default theme...
Best Frank
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: de.javasoft.plaf.synthetica.SyntheticaRootPaneUI cannot be cast to org.pushingpixels.substance.internal.ui.SubstanceRootPaneUI at org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities.getTitlePane(SubstanceCoreUtilities.java:1700) at org.pushingpixels.substance.api.painter.SubstancePainterUtils.getOffsetInRootPaneCoords(SubstancePainterUtils.java:49) at org.pushingpixels.substance.api.painter.decoration.ArcDecorationPainter.paintExtraBackground(ArcDecorationPainter.java:162) at org.pushingpixels.substance.api.painter.decoration.ArcDecorationPainter.paintDecorationArea(ArcDecorationPainter.java:69) at org.pushingpixels.substance.internal.painter.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:223) at org.pushingpixels.substance.internal.painter.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:182) at org.pushingpixels.substance.internal.painter.BackgroundPaintingUtils.update(BackgroundPaintingUtils.java:106) at org.pushingpixels.substance.internal.ui.SubstancePopupMenuUI.paint(SubstancePopupMenuUI.java:147) at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161) at javax.swing.JComponent.paintComponent(JComponent.java:780) at javax.swing.JComponent.paint(JComponent.java:1056) at javax.swing.JComponent.paintChildren(JComponent.java:889) at javax.swing.JComponent.paint(JComponent.java:1065) at javax.swing.JComponent.paintChildren(JComponent.java:889) at javax.swing.JComponent.paint(JComponent.java:1065) at javax.swing.JLayeredPane.paint(JLayeredPane.java:586) at javax.swing.JComponent.paintChildren(JComponent.java:889) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217) at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579) at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502) at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:306) at javax.swing.RepaintManager.paint(RepaintManager.java:1272) at javax.swing.JComponent.paint(JComponent.java:1042) at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39) at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79) at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116) at java.awt.Container.paint(Container.java:1975) at java.awt.Window.paint(Window.java:3904) at javax.swing.RepaintManager$4.run(RepaintManager.java:842) at javax.swing.RepaintManager$4.run(RepaintManager.java:814) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789) at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738) at javax.swing.RepaintManager.access$1200(RepaintManager.java:64) at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756) at java.awt.EventQueue.access$500(EventQueue.java:97) at java.awt.EventQueue$3.run(EventQueue.java:709) at java.awt.EventQueue$3.run(EventQueue.java:703) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) at java.awt.EventQueue.dispatchEvent(EventQueue.java:726) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: de.javaso
This looks like going from Synthetica to Substance misses updating at least one Window. SwingUtilities.updateComponentTreeUI should be called on all the Windows in your app.
I do SwingUtilities.updateComponentTreeUI on the main window and (since the weekend :)) on all open Dialogs. I also don't use heavy weight Popups in case they are used for nested menus :( I just tried it out again, about 25 changes, all went well including the correct look, and all code is in the AWT-Event-Thread so a race condition/threadig issue on the application side seems to be not the case. Weird...
Interesting. So it starts in SubstancePopupMenuUI.paint and then goes with the generic painting sequence. Probably can shortcut the title pane lookup there since it's not relevant for popup menus, but that doesn't sound like the right way to go - since it would be addressing the symptom.
But there might not be an API to enumerate all the open popup menus. Having said that, perhaps the code that switches the look-and-feel in your app should wait to run until after the menu click has been processed and the popups have been dismissed? Maybe as a separate event on the EDT and not right in the action listener?
There's also some code in https://stackoverflow.com/questions/8643672/list-all-jpopupmenu-currently-shown (first answer) to find all active popup menus. Probably there you'd apply updateComponentTreeUI on each one.
That led me to the right direction to reproduce and fix the issue. When the board was small enough so that the popup was larger than the window, the popup was a heavy component and the ComponentTreeUI wasn't updated. The stack overflow hint fixed it and was additionally simpler :) Invoke later seems to fix another small artefact which happens only with one Synthetica LaF so everything is fine now 👍 Thanks a lot.
Version of Substance
7.1.01
Version of Java
Oracle 1.8.0_151
Version of OS
Xubuntu 16.04.3 (kernel : 4.13.0-32-generic / os.arch : amd64
The issue you're experiencing (expected vs actual, screenshot, stack trace etc)
in my app I have chosen a substance L&F (with windows decorating painted by substance) and have open a JDialog and the main JFrame. When I switch to another L&F (in this case Synthetica, also using own windows decorating) I get an "Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Substance delegate used when Substance is not the current LAF [component JTextField in window bgblitz.EditCurPosition:'Edit Position' under Synthetica BlackMoon Look and Feel]" when no JDialog is open no exception occurs. I use simply UIManager.setLookAndFeel, nothing else. Any idea? (BTW the "known Issues" link on your main page is an 404)
I attached the trace. And important: Thanks a lot for your work on substance. I looked at it a decade (or even more ago) and doesn't used it. I stumbled upon it recently again and was deeply impressed. Boy has it grown! best Frank
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Substance delegate used when Substance is not the current LAF [component JTextField in window bgblitz.EditCurPosition:'Edit Position' under Synthetica BlackMoon Look and Feel] at org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities.traceSubstanceApiUsage(SubstanceCoreUtilities.java:1933) at org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities.getColorScheme(SubstanceColorSchemeUtilities.java:222) at org.pushingpixels.substance.internal.utils.SubstanceColorUtilities.getDefaultBackgroundColor(SubstanceColorUtilities.java:817) at org.pushingpixels.substance.internal.utils.SubstanceColorUtilities.getBackgroundFillColor(SubstanceColorUtilities.java:737) at org.pushingpixels.substance.internal.utils.SubstanceTextUtilities.getTextBackgroundFillColor(SubstanceTextUtilities.java:502) at org.pushingpixels.substance.internal.utils.SubstanceTextUtilities.paintTextCompBackground(SubstanceTextUtilities.java:492) at org.pushingpixels.substance.internal.ui.SubstanceTextFieldUI.paintBackground(SubstanceTextFieldUI.java:156) at javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:726) at javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:881) at javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:860) at org.pushingpixels.substance.internal.ui.SubstanceTextFieldUI.update(SubstanceTextFieldUI.java:285) at javax.swing.JComponent.paintComponent(JComponent.java:780) at javax.swing.JComponent.paint(JComponent.java:1056) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210) at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290) at javax.swing.RepaintManager.paint(RepaintManager.java:1272) at javax.swing.JComponent._paintImmediately(JComponent.java:5158) at javax.swing.JComponent.paintImmediately(JComponent.java:4969) at javax.swing.RepaintManager$4.run(RepaintManager.java:831) at javax.swing.RepaintManager$4.run(RepaintManager.java:814) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789) at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738) at javax.swing.RepaintManager.access$1200(RepaintManager.java:64) at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756) at java.awt.EventQueue.access$500(EventQueue.java:97) at java.awt.EventQueue$3.run(EventQueue.java:709) at java.awt.EventQueue$3.run(EventQueue.java:703) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) at java.awt.EventQueue.dispatchEvent(EventQueue.java:726) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)