PyQt5实现绘制矩形时动态裁剪半透明遮罩区域的问题
屏幕区域高亮工具代码修正
需求:实现全屏半透明灰色遮罩,拖动鼠标时从遮罩中裁剪出清晰矩形区域,同时显示红色边框标记该区域。原代码问题是拖动时遮罩消失,无法持续保留遮罩并裁剪新区域。
修正后的完整代码
import sys from PyQt5.QtCore import Qt from PyQt5.QtGui import QBrush, QColor, QPainter, QPen from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QDesktopWidget class MainWidget(QWidget): def __init__(self): super().__init__() self.setWindowTitle("区域高亮工具") self.setGeometry(100, 100, 200, 200) self.screenshotButton = QPushButton("开始", self) self.screenshotButton.move(50, 50) self.screenshotButton.clicked.connect(self.openTransparentWidget) def openTransparentWidget(self): self.close() self.transparentWidget = TransparentWidget() self.transparentWidget.show() class TransparentWidget(QWidget): def __init__(self): super().__init__() desktop = QDesktopWidget() screen_rect = desktop.screenGeometry() self.setGeometry(screen_rect) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground) self.start_pos = None self.end_pos = None self.mouse_pressed = False def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.mouse_pressed = True self.start_pos = event.pos() def mouseMoveEvent(self, event): if self.mouse_pressed: self.end_pos = event.pos() self.update() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.mouse_pressed = False def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) # 绘制全屏半透明灰色遮罩 mask_brush = QBrush(QColor(200, 200, 200, 128)) painter.setBrush(mask_brush) painter.drawRect(self.rect()) # 从遮罩中裁剪拖动的矩形区域,并绘制红色边框 if self.start_pos and self.end_pos: x = min(self.start_pos.x(), self.end_pos.x()) y = min(self.start_pos.y(), self.end_pos.y()) width = abs(self.start_pos.x() - self.end_pos.x()) height = abs(self.start_pos.y() - self.end_pos.y()) crop_rect = Qt.QRect(x, y, width, height) # 清除遮罩区域,显示下方屏幕 painter.setCompositionMode(QPainter.CompositionMode_Clear) painter.drawRect(crop_rect) # 恢复混合模式,绘制红色边框 painter.setCompositionMode(QPainter.CompositionMode_SourceOver) pen = QPen(QColor(255, 0, 0), 2) painter.setPen(pen) painter.drawRect(crop_rect) app = QApplication(sys.argv) mainWidget = MainWidget() mainWidget.show() sys.exit(app.exec_())
关键修改说明
- 始终绘制遮罩:无论是否开始拖动,
paintEvent都会先绘制全屏半透明遮罩,解决原代码中遮罩消失的问题。 - 用混合模式裁剪区域:通过
CompositionMode_Clear清除拖动的矩形区域,让下方屏幕清晰显示。 - 独立绘制边框:清除区域后切换回
SourceOver模式绘制红色边框,避免边框被同步清除。 - 优化变量逻辑:将分散的坐标变量改为
start_pos/end_pos,代码逻辑更清晰。
效果:启动后点击「开始」进入全屏遮罩,按住左键拖动鼠标,会实时从遮罩中裁剪出清晰的矩形区域,同时显示红色边框,匹配示例图的高亮效果。
内容的提问来源于stack exchange,提问作者David O'Donovan
相关产品推荐
相关产品推荐

