You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11下用JLayer搭配JScrollPane时Synthetica外观抛出类转换异常

Java 11 + Synthetica 下JLayer结合JScrollPane抛出类转换异常的修复方案

问题描述

在Java 11环境中使用Synthetica外观时,将JLayer直接包裹JScrollPane会抛出类转换异常,但该场景在Java 8下可正常运行。

代码示例

public class TestFrame extends JFrame
{
  TestFrame()
  {
    this.setSize(300,400);
    this.getContentPane().setLayout(new FlowLayout());
    JTextArea textArea = new JTextArea(20, 20);
    JScrollPane scrollableTextArea = new JScrollPane(textArea);
    LayerUI<JScrollPane> layerUI = new LayerUI();
    JLayer<JScrollPane> jLayer = new JLayer(scrollableTextArea, layerUI);
    this.add(jLayer);
  }

  public static void main(String[] args)
  {
    try
    {
      UIManager.setLookAndFeel(new SyntheticaAluOxideLookAndFeel());
      TestFrame testFrame = new TestFrame();
      testFrame.setVisible(true);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}

错误堆栈信息

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: class javax.swing.JLayer cannot be cast to class javax.swing.JScrollPane (javax.swing.JLayer and javax.swing.JScrollPane are in module java.desktop of loader 'bootstrap')
    at de.javasoft.plaf.synthetica.painter.ScrollPanePainter.paintScrollPaneBorder(ScrollPanePainter.java:274)
    at de.javasoft.plaf.synthetica.painter.SyntheticaPainter.paintScrollPaneBorder(SyntheticaPainter.java:640)
    at java.desktop/javax.swing.plaf.synth.SynthScrollPaneUI.paintBorder(SynthScrollPaneUI.java:125)
    at java.desktop/javax.swing.plaf.synth.SynthBorder.paintBorder(SynthBorder.java:63)
    at java.desktop/javax.swing.JComponent.paintBorder(JComponent.java:967)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1075)
    at java.desktop/javax.swing.JLayer.paint(JLayer.java:475)
    at java.desktop/javax.swing.plaf.LayerUI.paint(LayerUI.java:80)
    at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
    at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:797)
    at java.desktop/javax.swing.JLayer.paint(JLayer.java:470)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:590)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5262)

修复方案

方案1:调整JLayer的包裹层级

不要直接用JLayer包裹JScrollPane,而是将JLayer应用到JScrollPane内部的视口组件(比如示例中的JTextArea),再将JLayer放入JScrollPane中。修改后的代码:

public class TestFrame extends JFrame
{
  TestFrame()
  {
    this.setSize(300,400);
    this.getContentPane().setLayout(new FlowLayout());
    JTextArea textArea = new JTextArea(20, 20);
    // 先给文本区域添加JLayer
    LayerUI<JTextArea> layerUI = new LayerUI<>();
    JLayer<JTextArea> jLayer = new JLayer<>(textArea, layerUI);
    // 将JLayer放入JScrollPane
    JScrollPane scrollableTextArea = new JScrollPane(jLayer);
    this.add(scrollableTextArea);
  }

  public static void main(String[] args)
  {
    try
    {
      UIManager.setLookAndFeel(new SyntheticaAluOxideLookAndFeel());
      TestFrame testFrame = new TestFrame();
      testFrame.setVisible(true);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}

方案2:自定义修复Synthetica的ScrollPanePainter

异常根源是Synthetica的ScrollPanePainter在Java 11中未处理JLayer包装的场景,直接强制转换组件类型。可以自定义Painter类覆盖原有逻辑,在转换前先判断组件类型:

import de.javasoft.plaf.synthetica.painter.ScrollPanePainter;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JLayer;
import javax.swing.JScrollPane;

public class FixedScrollPanePainter extends ScrollPanePainter {
    @Override
    public void paintScrollPaneBorder(Graphics g, JComponent c) {
        JScrollPane scrollPane = null;
        // 优先获取真正的JScrollPane组件
        if (c instanceof JScrollPane) {
            scrollPane = (JScrollPane) c;
        } else if (c instanceof JLayer) {
            JLayer<?> layer = (JLayer<?>) c;
            Object view = layer.getView();
            if (view instanceof JScrollPane) {
                scrollPane = (JScrollPane) view;
            }
        }
        // 调用原逻辑处理有效组件,否则执行默认逻辑
        if (scrollPane != null) {
            super.paintScrollPaneBorder(g, scrollPane);
        } else {
            super.paintScrollPaneBorder(g, c);
        }
    }
}

之后需要通过Synthetica的配置机制替换原有的Painter,具体可参考其官方自定义皮肤文档。

方案3:升级Synthetica至Java 11兼容版本

检查Synthetica官方是否发布了支持Java 11及以上版本的更新包,官方通常会修复这类跨版本兼容性问题。

内容的提问来源于stack exchange,提问作者Ashan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:42:51