为何提高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物理像素)显示,需要:
- 创建物理像素为逻辑尺寸2倍的QImage(即500×500)
- 设置
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
相关产品推荐
相关产品推荐

