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

PySide6中如何在QGraphicsItem上用鼠标绘制分割标注蒙版

实现QGraphicsScene上的蒙版绘制与导出功能

问题分析

当前代码仅完成了图像与蒙版的叠加显示,缺少鼠标绘制蒙版的交互逻辑和导出蒙版文件的功能。需要通过自定义可交互的蒙版Item来实现绘制,并添加导出方法保存最终蒙版。

修改后的完整代码

from PySide6.QtWidgets import (
    QWidget,
    QMainWindow,
    QApplication,
    QFileDialog,
    QStyle,
    QColorDialog,
    QGraphicsView,
    QGraphicsScene,
    QGraphicsPixmapItem,
)

from PySide6.QtCore import Qt, Slot, QStandardPaths, QObject, QPointF
from PySide6.QtGui import (
    QMouseEvent,
    QPaintEvent,
    QPen,
    QAction,
    QPainter,
    QColor,
    QPixmap,
    QIcon,
    QKeySequence,
    QPainterPath
)

from PySide6.QtUiTools import QUiLoader

import sys

loader = QUiLoader() #set up loader object

image_path = r"image.jpg"
mask_path = r"mask.png"

class DrawableMaskItem(QGraphicsPixmapItem):
    def __init__(self, pixmap):
        super().__init__(pixmap)
        self.setAcceptHoverEvents(True)
        self.setFlag(QGraphicsPixmapItem.ItemIsSelectable, False)
        self.setFlag(QGraphicsPixmapItem.ItemIsMovable, False)
        self.drawing = False
        self.last_point = QPointF()
        # 默认绘制参数:红色画笔,圆角笔触
        self.pen = QPen(QColor(255, 0, 0), 5)
        self.pen.setCapStyle(Qt.RoundCap)
        self.pen.setJoinStyle(Qt.RoundJoin)

    def setPenColor(self, color):
        self.pen.setColor(color)

    def setPenWidth(self, width):
        self.pen.setWidth(width)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.last_point = self.mapToScene(event.pos())
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.drawing and event.buttons() & Qt.LeftButton:
            current_point = self.mapToScene(event.pos())
            # 在蒙版Pixmap上绘制线条
            painter = QPainter(self.pixmap())
            painter.setPen(self.pen)
            painter.drawLine(self.last_point, current_point)
            painter.end()
            self.setPixmap(self.pixmap())
            self.last_point = current_point
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = False
        super().mouseReleaseEvent(event)

class UserInterface(QObject): #An object wrapping around our ui
    def __init__(self):
        super().__init__()
        self.ui = loader.load("paint3.ui", None)
        self.ui.setWindowTitle("Painter3")

        self.ui.button1.clicked.connect(self.do_something)
        # 绑定导出按钮(需确保ui文件中有export_button控件)
        if hasattr(self.ui, "export_button"):
            self.ui.export_button.clicked.connect(self.export_mask)
        self.mask_opacity = 0.8
        self.mask_item = None

    def show(self):
        self.ui.show()
    
    def do_something(self):
        scene = QGraphicsScene(self)

        # 添加原图到场景
        image = QPixmap(image_path)
        img_item = QGraphicsPixmapItem(image)
        scene.addItem(img_item)

        # 添加可绘制蒙版,自动适配原图尺寸
        mask = QPixmap(mask_path)
        if mask.size() != image.size():
            mask = mask.scaled(image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.mask_item = DrawableMaskItem(mask)
        self.mask_item.setOpacity(self.mask_opacity)
        scene.addItem(self.mask_item)

        self.ui.grapView.setScene(scene)
        # 设置视图支持拖动平移
        self.ui.grapView.setDragMode(QGraphicsView.ScrollHandDrag)

    def export_mask(self):
        if not self.mask_item:
            return
        # 弹出保存对话框,导出蒙版为PNG
        save_path, _ = QFileDialog.getSaveFileName(
            self.ui,
            "导出蒙版",
            QStandardPaths.writableLocation(QStandardPaths.PicturesLocation),
            "PNG文件 (*.png)"
        )
        if save_path:
            self.mask_item.pixmap().save(save_path, "PNG")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = UserInterface()
    w.show()
    sys.exit(app.exec())

关键实现说明

  • 自定义DrawableMaskItem:继承QGraphicsPixmapItem,重写鼠标事件实现绘制逻辑:
    • 鼠标按下时记录起始点并开启绘制状态
    • 鼠标拖动时在蒙版的QPixmap上实时绘制线条,更新Item显示
    • 鼠标释放时结束绘制状态
  • 蒙版适配处理:自动调整蒙版尺寸与原图匹配,避免绘制错位
  • 导出功能:通过QFileDialog获取保存路径,调用QPixmap.save()导出PNG格式蒙版
  • 可扩展参数:预留画笔颜色、宽度设置方法,可添加UI控件实现参数调节

注意事项

  1. 确保paint3.ui中包含grapView(建议修正命名为graphView)和export_button控件
  2. 初始蒙版mask.png建议使用透明背景的空图片,方便绘制标注
  3. 可根据需求扩展右键擦除、画笔样式切换等功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:53:22