如何在PyQt5 QPainter中获取精准鼠标指针坐标?
PyQt5绘制矩形时鼠标坐标偏移问题解决
问题描述
在PyQt5中使用QPainter类实时绘制矩形,视觉上鼠标指针位置与矩形的起止点明显不一致,需要获取准确的鼠标指针坐标并修正代码错误。
原代码
from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * import sys class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # self.setMouseTracking(True) self.initUi() self.drawing = False self.start_pos_x = 0 self.start_pos_y = 0 self.end_pos_x = 0 self.end_pos_y = 0 def initUi(self): self.setWindowTitle("Dummy") self.setGeometry(0, 0, 900, 600) self.show() def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self.drawing = True self.start_pos_x = event.globalX() self.start_pos_y = event.globalY() print(event.globalPos(), event.localPos(), event.x(), event.y()) def mouseMoveEvent(self, event): if(event.buttons() & Qt.MouseButton.LeftButton) & self.drawing: self.end_pos_x = event.globalX() self.end_pos_y = event.globalY() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: print(self.start_pos_x, self.start_pos_y, self.end_pos_x, self.end_pos_y) print(event.globalPos()) self.drawing = False def paintEvent(self, event): if self.drawing: canvas = QPainter(self) canvas.setPen(Qt.GlobalColor.blue) canvas.drawRect(self.start_pos_x, self.start_pos_y, self.end_pos_x, self.end_pos_y) app = QApplication(sys.argv) window = MainWindow() app.exec_()
错误原因
- 坐标系统混淆:使用
globalX()/globalY()获取的是屏幕全局坐标,而QPainter绘制时使用的是窗口局部坐标(相对于窗口客户区左上角的坐标),全局坐标包含了窗口在屏幕上的位置偏移,导致绘制位置错位。 - drawRect参数误用:
drawRect(x, y, width, height)的后两个参数是矩形的宽高,而非结束点坐标,直接传入结束点坐标会导致矩形尺寸错误(尤其是当结束点在起始点左上方时)。
修正后的代码
from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * import sys class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # self.setMouseTracking(True) self.initUi() self.drawing = False self.start_pos = QPoint() self.end_pos = QPoint() def initUi(self): self.setWindowTitle("Dummy") self.setGeometry(0, 0, 900, 600) self.show() def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self.drawing = True # 获取窗口局部坐标 self.start_pos = event.pos() def mouseMoveEvent(self, event): if(event.buttons() & Qt.MouseButton.LeftButton) and self.drawing: self.end_pos = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self.end_pos = event.pos() self.drawing = False self.update() def paintEvent(self, event): if self.drawing: canvas = QPainter(self) canvas.setPen(Qt.GlobalColor.blue) # 计算矩形的正确位置和尺寸:左上角取最小坐标,宽高取坐标差的绝对值 rect_x = min(self.start_pos.x(), self.end_pos.x()) rect_y = min(self.start_pos.y(), self.end_pos.y()) rect_width = abs(self.start_pos.x() - self.end_pos.x()) rect_height = abs(self.start_pos.y() - self.end_pos.y()) canvas.drawRect(rect_x, rect_y, rect_width, rect_height) app = QApplication(sys.argv) window = MainWindow() app.exec_()
关键修改说明
- 使用局部坐标:用
event.pos()(等价于event.x()/event.y())获取相对于窗口客户区的坐标,确保绘制坐标与鼠标位置匹配。 - 正确计算矩形参数:通过取起始点和结束点的最小x/y作为矩形左上角,坐标差的绝对值作为宽高,保证无论从哪个方向拖拽鼠标,都能正确绘制出矩形。
内容的提问来源于stack exchange,提问作者F T
相关产品推荐
相关产品推荐

