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

Windows10设备缩放超175%时SWT绘制图片报错求助

SWT高DPI下打印预览drawImage()参数错误的解决思路

核心问题定位

问题出在高DPI(175%及以上)场景下,设备缩放比例获取不准确,导致图像源/目标尺寸计算偏差,触发SWT.ERROR_INVALID_ARGUMENT(源区域尺寸超出图像实际像素范围)。

具体解决步骤

1. 替换内部API,获取真实缩放比例

放弃使用org.eclipse.swt.internal.DPIUtil.getDeviceZoom()(内部类,行为不稳定),改用Display.getDPI()计算准确的缩放系数:

Display display = Display.getCurrent();
// Windows默认96DPI对应100%缩放,以此计算实际缩放比例
double scaleX = display.getDPI().x / 96.0;
double scaleY = display.getDPI().y / 96.0;
// 统一取X/Y轴缩放(Windows通常X/Y一致)
double scale = Math.max(scaleX, scaleY);

该方法能准确返回175%→1.75、200%→2.0这类真实缩放值,避免之前的返回值失真问题。

2. 明确区分逻辑尺寸与物理像素尺寸

SWT在高DPI下,UI元素用逻辑尺寸(与缩放无关),图像缓冲区用物理像素尺寸(逻辑尺寸×缩放比例),绘制时需严格对应:

  • 若图像是按物理像素渲染的,绘制时:
    // b是物理像素尺寸的图像缓冲区
    int logicalWidth = (int) Math.round(b.getBounds().width / scale);
    int logicalHeight = (int) Math.round(b.getBounds().height / scale);
    
    // 源区域取图像完整物理像素,目标区域转逻辑尺寸
    gc.drawImage(b, 
                 0, 0, b.getBounds().width, b.getBounds().height, 
                 0, 0, logicalWidth, logicalHeight);
    
  • 确保srcWidth/srcHeight始终≤图像的实际物理宽度/高度,这是避免参数错误的关键。

3. 修正ImageData的创建逻辑

创建图像缓冲区时,基于逻辑尺寸乘以缩放比例得到物理像素尺寸,避免图像尺寸不足:

int logicalWidth = 800; // 原UI逻辑宽度
int logicalHeight = 600; // 原UI逻辑高度
int physicalWidth = (int) Math.round(logicalWidth * scale);
int physicalHeight = (int) Math.round(logicalHeight * scale);

// 按物理像素尺寸创建ImageData
ImageData imageData = new ImageData(physicalWidth, physicalHeight, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));

4. 检查GC的默认缩放变换

SWT的GC在高DPI模式下可能自动应用缩放变换,避免手动重复缩放:

Transform transform = gc.getTransform();
// 检查当前变换是否已有缩放因子
double currentScaleX = transform.getScaleX();
double currentScaleY = transform.getScaleY();

// 若GC已适配缩放,直接用逻辑尺寸绘制
if (Math.abs(currentScaleX - scale) < 0.01) {
    gc.drawImage(b, 0, 0, logicalWidth, logicalHeight);
}

5. 处理非整倍数缩放的取整误差

针对175%这类非整倍数缩放,用Math.round()替代直接截断取整,避免像素尺寸计算偏差:

// 错误示例:直接截断导致尺寸不足
int badPhysicalWidth = (int) (logicalWidth * scale);
// 正确示例:四舍五入保证像素数准确
int goodPhysicalWidth = (int) Math.round(logicalWidth * scale);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:25:29