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

如何解决Windows显示缩放导致JFrame截图显示模糊的问题?

问题

我做了个Java恶作剧程序,功能是截取屏幕截图后用JFrame展示,用户点击屏幕不会有任何响应(因为只是和图像交互)。但在Windows开启显示缩放(比如125%)时,原本1920x1080的BufferedImage会被显示成2400x1350的模糊像素化画面,恶作剧完全失效。我试过把图像按1/1.25比例缩小,但缩放后像素化还是很严重,请问怎么让程序不受系统显示缩放影响,按预期运行?

解决方案

核心是让Java Swing程序绕过系统的高DPI缩放适配,确保截图尺寸和窗口显示尺寸完全匹配,避免自动拉伸模糊。

1. 强制禁用Swing的UI缩放

在程序启动时强制设置UI缩放比例为1,让Swing忽略系统的DPI设置。有两种方式:

  • JVM参数启动:运行程序时添加参数 java -Dsun.java2d.uiScale=1 Test
  • 代码内设置:在main方法最开头添加一行,提前配置系统属性(推荐,无需修改启动命令):
    System.setProperty("sun.java2d.uiScale", "1");
    

2. 修正截图的缩放偏差

Windows高DPI环境下,GDI32Util.getScreenshot获取的截图是经过系统缩放后的尺寸,需要反向缩放回原窗口的实际像素尺寸,同时使用高质量缩放算法避免模糊:

  • 通过JNA获取目标窗口的DPI值,计算缩放比例
  • 使用Graphics2D的双线性插值算法对截图进行缩放,保证清晰度
修改后的完整代码
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.GDI32Util;

public class Test {
    public static void main(String[] args) throws Exception {
        // 强制禁用UI缩放,忽略系统DPI设置
        System.setProperty("sun.java2d.uiScale", "1");

        BufferedImage capture = captureNotepadWindow();
        int width = capture.getWidth();
        int height = capture.getHeight();
        System.out.println(width + "," + height);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JLabel(new ImageIcon(capture)));
        frame.setPreferredSize(new Dimension(width, height));
        frame.setUndecorated(true);
        frame.pack();
        
        // 精准定位窗口到原记事本位置,增强恶作剧效果
        HWND notepadHwnd = User32.INSTANCE.FindWindow("Notepad", null);
        RECT rect = new RECT();
        User32.INSTANCE.GetWindowRect(notepadHwnd, rect);
        frame.setLocation(rect.left, rect.top);
        
        frame.setVisible(true);
    }

    public static BufferedImage captureNotepadWindow() throws Exception {
        HWND notepadHwnd = User32.INSTANCE.FindWindow("Notepad", null);
        if (notepadHwnd == null) {
            throw new Exception("未找到记事本窗口");
        }

        // 获取目标窗口的DPI,计算系统缩放比例
        int dpi = User32.INSTANCE.GetDpiForWindow(notepadHwnd);
        double scale = dpi / 96.0; // 96为Windows默认DPI值

        BufferedImage originalCapture = GDI32Util.getScreenshot(notepadHwnd);
        // 计算原窗口的实际像素尺寸
        int targetWidth = (int) (originalCapture.getWidth() / scale);
        int targetHeight = (int) (originalCapture.getHeight() / scale);

        // 使用高质量缩放算法生成适配尺寸的截图
        BufferedImage scaledCapture = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = scaledCapture.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(originalCapture, 0, 0, targetWidth, targetHeight, null);
        g2d.dispose();

        return scaledCapture;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:44:50