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

如何在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_()

错误原因

  1. 坐标系统混淆:使用globalX()/globalY()获取的是屏幕全局坐标,而QPainter绘制时使用的是窗口局部坐标(相对于窗口客户区左上角的坐标),全局坐标包含了窗口在屏幕上的位置偏移,导致绘制位置错位。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:02:39