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

为何提高devicePixelRatio会使QImage显示尺寸缩小?

关于QImage设置devicePixelRatio后显示尺寸缩小的疑问

你提到devicePixelRatio用于将设备独立像素转换为设备实际物理像素,比如Qt Summit 2015中的案例:300×200的QWidget若devicePixelRatio为2,会在屏幕上渲染为600×400的物理尺寸。但你编写的代码出现了相反行为:给QImage设置self.image.setDevicePixelRatio(2)后,图像实际显示尺寸减半。你原本理解为每个设备独立像素占据2个物理像素,QImage显示尺寸应该翻倍,想知道为何实际是缩小。

你的代码如下:

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QImage, QPainter
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget

DEFAULT_WIDTH = DEFAULT_HEIGHT = 250


class QPainterWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.image = QImage(DEFAULT_WIDTH, DEFAULT_HEIGHT, QImage.Format_RGB32)
        self.image.fill(Qt.green)
        self.image.setDevicePixelRatio(2)
        painter = QPainter(self.image)
        painter.end()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(0, 0, self.image)
        painter.end()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(DEFAULT_WIDTH, DEFAULT_HEIGHT)
        self.setCentralWidget(QPainterWidget())


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

原因解释

核心是QImage的devicePixelRatio逻辑和QWidget完全相反:

  • 对于QWidget:devicePixelRatio是"逻辑尺寸转物理尺寸"的放大系数——逻辑尺寸300×200 × 系数2 = 600×400物理像素,所以显示尺寸翻倍。
  • 对于QImage:devicePixelRatio是"物理像素转逻辑尺寸"的缩小系数——你创建的图像物理像素是250×250,设置系数2后,Qt会认为它的逻辑尺寸是250/2=125×125。当你用drawImage绘制时,Qt会按逻辑尺寸渲染,所以原本250×250的像素图像被缩放到125×125显示,视觉上就减半了。

解决方法

如果想让QImage以250×250的逻辑尺寸(对应500×500物理像素)显示,需要:

  1. 创建物理像素为逻辑尺寸2倍的QImage(即500×500)
  2. 设置devicePixelRatio=2,让Qt识别它的逻辑尺寸为250×250,和Widget尺寸匹配

修改后的代码:

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QImage, QPainter
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget

DEFAULT_WIDTH = DEFAULT_HEIGHT = 250


class QPainterWidget(QWidget):
    def __init__(self):
        super().__init__()
        # 创建2倍物理像素尺寸的图像
        self.image = QImage(DEFAULT_WIDTH * 2, DEFAULT_HEIGHT * 2, QImage.Format_RGB32)
        self.image.fill(Qt.green)
        self.image.setDevicePixelRatio(2)
        painter = QPainter(self.image)
        painter.end()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(0, 0, self.image)
        painter.end()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(DEFAULT_WIDTH, DEFAULT_HEIGHT)
        self.setCentralWidget(QPainterWidget())


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:01:02