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

如何在PyQt5中通过鼠标操作在QLabel展示的图片上绘制矩形

PyQt5在QLabel承载的图片上绘制矩形的实现方案

问题根源

你现有代码的核心问题如下:

  1. 重写的是父容器QWidget的paintEvent,矩形绘制在父控件层面,和QLabel的图片层级分离,会出现错位问题
  2. 鼠标事件获取的是父控件的全局坐标,没有对应QLabel的内部相对坐标,绘制位置会偏移

解决方案

自定义可绘制矩形的QLabel子类,所有绘制逻辑和鼠标事件都封装在子类内部,直接作用于QLabel控件本身。

完整可运行代码

import sys
from PyQt5 import QtWidgets, QtCore, QtGui

class DrawableLabel(QtWidgets.QLabel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()
        self.original_pixmap = None

    def setPixmap(self, pixmap):
        self.original_pixmap = pixmap
        super().setPixmap(pixmap)

    def paintEvent(self, event):
        super().paintEvent(event)
        if self.begin.isNull() or self.end.isNull():
            return
        qp = QtGui.QPainter(self)
        br = QtGui.QBrush(QtGui.QColor(100, 10, 10, 40))
        qp.setBrush(br)
        qp.drawRect(QtCore.QRect(self.begin, self.end).normalized())

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = event.pos()
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.end = event.pos()
        self.update()

class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(30,30,600,400)
        self.picture = DrawableLabel(self)
        self.picture.setGeometry(QtCore.QRect(10, 60, 1111, 541))
        self.picture.setMinimumSize(QtCore.QSize(0, 0))
        self.picture.setStyleSheet("background-color: rgb(188, 188, 188);")
        self.picture.setText("")
        # 替换为你的本地图片路径
        pixmap = QtGui.QPixmap("G:/JOB files/JoBfiles/300/5.jpg")
        self.picture.setPixmap(pixmap)
        self.picture.setScaledContents(True)
        self.picture.setObjectName("picture")
        self.show()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ui = MyWidget()
    mainwindow = QtWidgets.QStackedWidget()
    mainwindow.addWidget(ui)
    screen = app.primaryScreen()
    size = screen.size()
    mainwindow.setFixedWidth(size.width())
    mainwindow.setFixedHeight(size.height())
    mainwindow.showMaximized()
    mainwindow.show()
    sys.exit(app.exec_())

补充说明

  • 代码中调用normalized()方法是为了适配任意方向的鼠标拖拽,不管你从左上往右下拖还是反向拖拽,都能正常显示矩形
  • 如果需要将绘制的矩形永久保存到图片文件中,可在mouseReleaseEvent中将矩形绘制到self.original_pixmap上,再调用self.original_pixmap.save()方法存储即可
  • 因为你开启了setScaledContents(True),如果需要获取矩形对应原始图片的坐标,需要将QLabel内的相对坐标按缩放比例换算即可。

内容的提问来源于stack exchange,提问作者NaQi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:15:06