Changing Java Swing themes on runtime causes JTable bugs

170 views Asked by At

I want to change look & feels on runtime in my Java Swing GUI.

For that I'm calling UIManager.setLookAndFeel() and SwingUtilities.updateComponentTreeUI() to refresh the GUI which seems to work but the latter method causes a severe GUI bug: Any tab with a JTable in it causes the following exception and fail to render properly:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at com.sun.java.swing.plaf.windows.WindowsTableHeaderUI$XPDefaultRenderer.paint(WindowsTableHeaderUI.java:171)
    at javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:151)
    at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderUI.java:710)
    at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:652)
    at javax.swing.plaf.synth.SynthTableHeaderUI.paint(SynthTableHeaderUI.java:173)
    at javax.swing.plaf.synth.SynthTableHeaderUI.update(SynthTableHeaderUI.java:144)
    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.JViewport.paint(JViewport.java:728)
    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.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.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.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.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.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:1978)
    at java.awt.Window.paint(Window.java:3906)
    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:74)
    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$$$capture(InvocationEvent.java:311)

It gives a "ghosting" effect of rendering items only when the mouse is moved over them and it's unusable.

A Java bug for this has already been reported here. I'm running Java version 1.8.0_231. Is there a way to fix this problem or maybe I'm doing something wrong?

private static void setHeaderAlignment(JTable table)
{
    JTableHeader header = table.getTableHeader();
    HeaderRenderer headerRenderer = new HeaderRenderer(table);
    header.setDefaultRenderer(headerRenderer);
}
2

There are 2 answers

0
BullyWiiPlaza On BEST ANSWER

Not setting a default renderer fixes the bug. It appears as if I don't need the header renderer at all so I'm happy with dropping it entirely.

0
BendaThierry.com On

maybe because your JTableHeader header is a local variable of your static method.

Try extracting it as a class property in your class and set it at some time to your JTable. Then call your static method.

It will provide access to that property before trying to set its own default renderer.