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控件实现参数调节
注意事项
- 确保
paint3.ui中包含grapView(建议修正命名为graphView)和export_button控件 - 初始蒙版
mask.png建议使用透明背景的空图片,方便绘制标注 - 可根据需求扩展右键擦除、画笔样式切换等功能
内容的提问来源于stack exchange,提问作者vuict
相关产品推荐
相关产品推荐

