PyQt5向QLabel添加QPixmap后放大窗口画笔偏离鼠标坐标的原因是什么
问题原因分析
你的问题本质是坐标系统不匹配,核心原因有两点:
- QLabel默认
scaledContents属性为关闭状态,你放大窗口时QLabel的尺寸会被拉伸变大,但内部承载的QPixmap分辨率始终是固定的900×600,没有同步变化,QLabel只是把低分辨率的Pixmap拉伸后展示到自身的大尺寸区域上。你直接获取的鼠标坐标是相对于已经放大的窗口/QLabel的坐标,直接用这个坐标往固定尺寸的Pixmap上绘制,自然会出现位置偏移。 - 你监听的是QMainWindow的鼠标事件,拿到的
e.x()、e.y()是相对于主窗口的坐标,不是相对于QLabel内部Pixmap的坐标,如果窗口带有菜单栏、状态栏这类组件,本身就会存在固有坐标偏移,窗口放大后偏移差值会更明显。
修复方案
你可以按照以下步骤调整代码解决问题:
- 给QLabel设置
setScaledContents(True),让Pixmap跟随QLabel的尺寸自动适配显示 - 把获取到的鼠标坐标先转换为相对于QLabel的坐标,再映射到Pixmap本身的尺寸坐标系中
- 如果需要支持窗口自由缩放后画布同步扩容,可以监听窗口的resize事件,动态调整QPixmap的尺寸,注意调整时要把之前的绘制内容拷贝到新的Pixmap中,避免内容丢失
修复后的参考代码如下:
import sys from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt class MainWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setMinimumSize(900,600) self.label = QtWidgets.QLabel() self.label.setScaledContents(True) # 核心配置:让pixmap跟随label缩放 self.canvas_size = QtCore.QSize(900, 600) self.canvas = QtGui.QPixmap(self.canvas_size) self.canvas.fill(Qt.white) self.label.setPixmap(self.canvas) self.setCentralWidget(self.label) self.last_x, self.last_y = None, None def mouseMoveEvent(self, e): if self.last_x is None: self.last_x = e.x() self.last_y = e.y() return # 转换鼠标坐标到pixmap的坐标系统 label_pos = self.label.mapFrom(self, e.pos()) pix_x = label_pos.x() * self.canvas_size.width() / self.label.width() pix_y = label_pos.y() * self.canvas_size.height() / self.label.height() last_pix_x = self.last_x * self.canvas_size.width() / self.label.width() last_pix_y = self.last_y * self.canvas_size.height() / self.label.height() painter = QtGui.QPainter(self.label.pixmap()) painter.drawLine(last_pix_x, last_pix_y, pix_x, pix_y) painter.end() self.update() self.last_x = e.x() self.last_y = e.y() def mouseReleaseEvent(self, e): self.last_x = None self.last_y = None app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() app.exec_()
内容的提问来源于stack exchange,提问作者Amanullah Amini
相关产品推荐
相关产品推荐

