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

Java Swing JButton底部出现渲染伪影(Artifacts)的解决方法及问题排查咨询

Java Swing JButton底部出现渲染伪影(Artifacts)的解决方法及问题排查咨询

看起来你在Windows 11环境下使用Java 24/26预览版运行Swing代码时,遇到了JButton底部出现黑色残留伪影的问题,先帮你梳理问题背景,再给出几个针对性的排查和解决方向:

你的问题背景与复现代码

你通过命令行直接运行以下启用预览特性的Java代码,JButton底部出现了异常的黑色伪影,且在Java 26版本中也能复现该问题:

import module java.desktop;

void main() {
    SwingUtilities.invokeLater(() -> {
        final JFrame frame = new JFrame();
        frame.setTitle("This is a title");
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());

        final JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));

        final var urlAsString = "https://b.thumbs.redditmedia.com/2rTE46grzsr-Ll3Q.png";
        try {
            final var url = new URI(urlAsString).toURL();
            final BufferedImage image = ImageIO.read(url);
            final var redditLogo = new JLabel(new ImageIcon(image));
            topPanel.add(redditLogo);
        } catch (final Exception exception) {
            throw new RuntimeException("Failed to fetch image from " + urlAsString, exception);
        }

        final JButton hotButton = new JButton();
        hotButton.setText("hot");
        topPanel.add(hotButton);

        mainPanel.add(topPanel, BorderLayout.NORTH);
        frame.add(mainPanel);
        frame.setVisible(true);
    });
}

针对性排查与解决方向

1. 优先禁用Swing硬件加速(Windows环境常见修复)

Windows下Swing的硬件加速(Direct3D)经常会和显卡驱动、JDK版本出现兼容性问题,导致渲染伪影。你可以在命令行启动时添加以下参数试试:

java --enable-preview -Dsun.java2d.d3d=false YourClassName.java

或者替换为-Dsun.java2d.noddraw=true,这两个参数都会强制Swing使用软件渲染,绕过可能有问题的硬件加速模块。

2. 修正布局的垂直对齐逻辑

你使用了BoxLayout.X_AXIS作为topPanel的布局,默认情况下组件的垂直对齐可能不一致,导致按钮的绘制区域被错误计算,出现溢出伪影。可以给所有topPanel内的组件添加垂直居中对齐:

import java.awt.Component; // 记得添加这个导入

// 在添加组件到topPanel前添加以下代码
topPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
redditLogo.setAlignmentY(Component.CENTER_ALIGNMENT);
hotButton.setAlignmentY(Component.CENTER_ALIGNMENT);

强制让图片标签和按钮在垂直方向居中对齐,避免布局计算错误导致的绘制异常。

3. 显式设置组件的绘制属性

有时候Swing组件的默认不透明性、边框设置会引发渲染bug,你可以尝试显式配置按钮的相关属性:

hotButton.setOpaque(true);
// 显式设置边框,避免默认边框的绘制问题
hotButton.setBorder(BorderFactory.createLineBorder(UIManager.getColor("Button.borderColor")));
// 或者添加空边框调整内部间距,避免内容溢出
hotButton.setBorder(BorderFactory.createEmptyBorder(3, 6, 3, 6));

添加后可以在组件添加到面板后强制触发重绘:

topPanel.revalidate();
topPanel.repaint();

4. 切换到稳定版JDK

你当前使用的是Java 24/26的预览版,这类版本的Swing模块可能存在未修复的实验性bug(毕竟Swing在新JDK版本中的维护优先级较低)。建议切换到Java 21 LTS(长期支持版)再测试,看伪影是否消失,这能排除预览版JDK本身的问题。

5. 检查图片加载对布局的影响

图片的尺寸可能超出了topPanel的预期高度,导致布局挤压按钮的绘制区域。可以在加载图片后打印尺寸,确认是否存在异常:

System.out.println("Loaded image size: " + image.getWidth() + "x" + image.getHeight());

如果图片过高,可以缩放图片后再创建ImageIcon:

Image scaledImage = image.getScaledInstance(-1, 32, Image.SCALE_SMOOTH); // 固定高度32,宽度按比例缩放
final var redditLogo = new JLabel(new ImageIcon(scaledImage));

避免过大的图片导致面板高度被异常拉伸,影响按钮的绘制。

建议排查顺序

推荐你先从禁用硬件加速开始测试,这个是Windows下Swing渲染伪影最常见的解决方法;如果无效再尝试调整布局对齐,最后再考虑JDK版本切换。如果有新的测试结果,可以补充更多细节,方便进一步排查~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 03:08:27