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
相关产品推荐
相关产品推荐

