示例#1
0
文件: start.py 项目: aksenof/vsuet
 def mre(self, event):  # функция отпускания мыши
     im_width, im_height = int(self.im.size[0]), int(
         self.im.size[1])  # ширина и высота изображения
     gv_width = list(QRect.getRect(self.ui.graphicsView.geometry()))[
         2]  # ширина обозревателя graphicsView
     gv_height = list(QRect.getRect(self.ui.graphicsView.geometry()))[
         3]  # высота обозревателя graphicsView
     self.rect = self.rubberBand.geometry()
     self.coords = list(QRect.getCoords(
         self.rect))  # координаты выделенного прямоугольника
     self.coords[2] = self.borders(self.coords[2], gv_width)
     self.coords[3] = self.borders(self.coords[3], gv_height)
     c = self.coords
     self.rubberBand.hide()  # скрыть прямоугольник
     self.ui.label_7.setText("select coords: {} ".format(str(self.coords)))
     scr_v = int(self.ui.graphicsView.verticalScrollBar().sliderPosition()
                 )  # позиция вертикального скрола
     scr_h = int(self.ui.graphicsView.horizontalScrollBar().sliderPosition(
     ))  # позиция горизонтального скрола
     self.real_coords = [
         c[0] + scr_h, c[1] + scr_v, c[2] + scr_h, c[3] + scr_v
     ]  # реальные координаты
     self.real_coords[2] = self.borders(self.real_coords[2], im_width)
     self.real_coords[3] = self.borders(self.real_coords[3], im_height)
     self.ui.label_8.setText("real coords: {} ".format(str(
         self.real_coords)))
    def selected(self, rect: QRect):
        x = rect.getRect()[0]
        y = rect.getRect()[1]
        width = rect.getRect()[2]
        height = rect.getRect()[3]
        img = self.reference_img[y:y + height, x:x + width, :]

        self.workflow[self.row] = (self.workflow[self.row][0], img)
        self.build_content()
示例#3
0
def qrect_to_json(val: QRect):
    return json.dumps(val.getRect())
示例#4
0
class LabelCanvas(QWidget):
    def __init__(self,
                 statusbar=None,
                 labelCoordinates=None,
                 labelQLabel=None,
                 labelEdit=None):
        super(LabelCanvas, self).__init__()
        self.statusbar = statusbar
        self.labelCoordinates = labelCoordinates
        self.labelEdit = labelEdit
        self.labelQLabel = labelQLabel
        if self.labelQLabel:
            self.labelQLabel.hide()
        if self.labelEdit:
            self.labelEdit.hide()
            self.labelEdit.returnPressed.connect(self.labelEditEnterPress)

        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.WheelFocus)

        self.painter = QPainter()
        self.scaleRate = 0.2

        self.pixmap = QPixmap('icon/sample.jpg')
        self.pmapRect = self.pixmap.rect()
        self.pmapShowAreaRect = self.pixmap.rect()
        self.drag = False
        self.labels = ()

        self.mousex = 0
        self.mousey = 0
        self.labels = []
        self.templabel = []
        self.labeling = False
        self.labelsRect = []
        self.deleteRects = []
        self.textRects = []

    def loadPixmap(self, pixmap, labels=None):
        self.pixmap = pixmap
        self.pmapRect = pixmap.rect()
        self.pmapShowAreaRect = pixmap.rect()
        self.labels.clear()
        if labels:
            self.labels.extend(labels)
        self.repaint()

    def paintEvent(self, e):
        self.painter.begin(self)

        # 绘制图片内容
        self.painter.drawPixmap(self.rect(), self.pixmap,
                                self.pmapShowAreaRect)

        # 绘制图片区域预览
        self.painter.setPen(QColor(0, 0, 0))
        scale = min(self.width() / self.pixmap.width() / 5,
                    self.height() / self.pixmap.height() / 5)
        self.pmapPreRect = QRect(0, 0,
                                 self.pixmap.width() * scale,
                                 self.pixmap.height() * scale)
        margin = int(min(self.width(), self.height()) / 16)
        self.pmapPreRect.moveTopRight(QPoint(self.width() - margin, margin))
        self.painter.drawRect(self.pmapPreRect)

        # 绘制图片展示区域预览
        self.painter.setPen(QColor(255, 0, 0))
        pmapprerect = self.pmapPreRect.getRect()
        pmapshowarearect = self.pmapShowAreaRect.getRect()
        x = pmapprerect[0] + self.pmapPreRect.width(
        ) * pmapshowarearect[0] / self.pixmap.width()
        y = pmapprerect[1] + self.pmapPreRect.height(
        ) * pmapshowarearect[1] / self.pixmap.height()
        w = scale * self.pmapShowAreaRect.width()
        h = scale * self.pmapShowAreaRect.height()
        self.pmapShowAreaPreRect = QRect(x, y, w, h)
        self.painter.drawRect(self.pmapShowAreaPreRect)

        self.dragAreaRect = QRect(
            self.pmapPreRect.x() - self.pmapShowAreaPreRect.width(),
            self.pmapPreRect.y() - self.pmapShowAreaPreRect.height(),
            self.pmapShowAreaPreRect.width() + self.pmapPreRect.width(),
            self.pmapShowAreaPreRect.height() + self.pmapPreRect.height())

        # 绘制缩放中心点标线
        self.painter.setPen(QColor(255, 0, 0))
        self.painter.drawLine(self.width() / 3,
                              self.height() / 2,
                              self.width() / 3 * 2,
                              self.height() / 2)
        self.painter.drawLine(self.width() / 2,
                              self.height() / 3,
                              self.width() / 2,
                              self.height() / 3 * 2)

        # 绘制鼠标位置标线
        if self.labeling:
            self.painter.setPen(QColor(0, 0, 0))
            self.painter.drawLine(self.mousex, 0, self.mousex, self.height())
            self.painter.drawLine(0, self.mousey, self.width(), self.mousey)

        # 绘制正在编辑中的label位置
        if self.templabel:
            for i in range(int(len(self.templabel) / 2)):
                imagex, imagey = self.templabel[0 +
                                                2 * i], self.templabel[1 +
                                                                       2 * i]
                if self.pmapShowAreaRect.contains(imagex, imagey):
                    widgetx, widgety = self.imageXY2WidgetXY(imagex, imagey)
                    self.painter.setPen(QPen(Qt.red, 5))
                    self.painter.drawPoint(widgetx, widgety)

                    pen = QPen(Qt.black, 2, Qt.SolidLine)
                    pen.setStyle(Qt.DashDotDotLine)
                    self.painter.setPen(pen)
                    self.painter.drawLine(widgetx, 0, widgetx, self.height())
                    self.painter.drawLine(0, widgety, self.width(), widgety)

        # 绘制已标记内容
        self.deleteRects.clear()
        self.textRects.clear()

        self.painter.setPen(QColor(168, 34, 3))
        self.painter.setFont(QFont('Decorative', 12))
        metrics = self.painter.fontMetrics()
        deleteRectWidth, deleteRectHeight = metrics.height(
        ) * 1.2, metrics.height() * 1.2

        separatorheight = margin / 10

        pmapprerect = self.pmapPreRect.getRect()
        topRightx, topRighty = self.width(
        ) - margin, pmapprerect[1] + pmapprerect[3] + margin / 4
        for i in range(len(self.labels)):
            label = self.labels[i]
            # 绘制文字展示信息
            text = label[4]
            deleteRect = QRect(
                topRightx - deleteRectWidth,
                topRighty + (deleteRectHeight + separatorheight) * i,
                deleteRectWidth, deleteRectHeight)
            self.painter.drawRect(deleteRect)
            self.painter.drawLine(deleteRect.topLeft(),
                                  deleteRect.bottomRight())
            self.painter.drawLine(deleteRect.topRight(),
                                  deleteRect.bottomLeft())
            self.deleteRects.append(deleteRect)

            deleterect = deleteRect.getRect()
            textWidth, textHeight = metrics.width(text), metrics.height()
            textRect = QRect(deleterect[0] - textWidth - metrics.height(),
                             deleterect[1], textWidth + metrics.height(),
                             deleterect[3])
            self.painter.drawRect(textRect)
            self.painter.drawText(textRect, Qt.AlignCenter, text)
            self.textRects.append(textRect)
            # 在图片上绘制标签矩形框
            labelPixmapX, labelPixmapY, labelPixmapWidth, labelPixmapHeight = label[:
                                                                                    4]
            labelPixmapRect = QRect(labelPixmapX, labelPixmapY,
                                    labelPixmapWidth, labelPixmapHeight)
            intersectedRect = self.pmapShowAreaRect.intersected(
                labelPixmapRect)
            if intersectedRect:
                pixmapTopLeftPoint, pixmapBottomRightPoint = intersectedRect.topLeft(
                ), intersectedRect.bottomRight()
                widgetTopLeftPointX, widgetTopLeftPointY = self.imageXY2WidgetXY(
                    pixmapTopLeftPoint.x(), pixmapTopLeftPoint.y())
                widgetTopLeftPoint = QPoint(widgetTopLeftPointX,
                                            widgetTopLeftPointY)
                widgetBottomRightPointX, widgetBottomRightPointY = self.imageXY2WidgetXY(
                    pixmapBottomRightPoint.x(), pixmapBottomRightPoint.y())
                widgetBottomRightPoint = QPoint(widgetBottomRightPointX,
                                                widgetBottomRightPointY)
                labelRect = QRect(widgetTopLeftPoint, widgetBottomRightPoint)
                self.painter.drawRect(labelRect)
                # 绘制标签名
                labelrect = labelRect.getRect()
                textRect1 = QRect(labelrect[0], labelrect[1] - textHeight,
                                  textWidth, textHeight)
                # self.painter.drawRect(textRect1)
                self.painter.drawText(textRect1, Qt.AlignCenter, text)

        self.painter.end()

    # 将图片中像素坐标转化为控件坐标
    def imageXY2WidgetXY(self, imagex, imagey):
        pmapshowarearect = self.pmapShowAreaRect.getRect()
        widgetx = (imagex -
                   pmapshowarearect[0]) / pmapshowarearect[2] * self.width()
        widgety = (imagey -
                   pmapshowarearect[1]) / pmapshowarearect[3] * self.height()
        return widgetx, widgety

    # 恢复图片初加载状态
    def restart(self):
        self.pmapRect = self.pixmap.rect()
        self.pmapShowAreaRect = self.pixmap.rect()
        self.repaint()

    # 初始化一个新的标签
    def label(self):
        self.templabel.clear()
        self.labeling = True
        if self.labelQLabel:
            self.labelQLabel.setText('')
            self.labelQLabel.show()
        self.status('开始创建标签', delay=500)
        self.repaint()

    # 移除最后一次添加的像素点
    def undo(self):
        self.removeTempPoint()

    # 返回标签内容
    def save(self):
        self.clearStatus()
        return self.labels

    def clearStatus(self):
        if self.labelQLabel:
            self.labelQLabel.hide()
        if self.labelEdit:
            self.labelEdit.hide()
        if self.templabel:
            self.templabel.clear()
        self.labeling = False
        self.repaint()

    # 添加标记点
    def addTempPoint(self, x, y):
        if self.labelQLabel.isHidden():
            self.labelQLabel.show()

        self.templabel.append(x)
        self.templabel.append(y)

        self.statusLabel('创建标签->' + str(self.templabel))

        if len(self.templabel) == 4:
            self.statusLabel('标签内容为->' + str(self.templabel) + ' 请输入标签名->')
            self.labeling = False
            self.labelEdit.setText('')
            self.labelEdit.setFocus()
            self.labelEdit.show()
            self.repaint()

    # 移除标记点
    def removeTempPoint(self):
        if self.templabel:
            self.templabel = self.templabel[:-2]
            self.repaint()

            self.labelEdit.setText('')
            self.labelEdit.hide()
            self.labelQLabel.setText('标签内容->' + str(self.templabel))
            if len(self.templabel) == 0:
                self.labelQLabel.hide()

    # 监听滚轮事件
    def wheelEvent(self, event):
        if event.angleDelta:
            if event.angleDelta().y() / 120 >= 1:
                self.enlargeByCenter()
            else:
                self.narrowByCenter()

    # 监听鼠标双击事件
    def mouseDoubleClickEvent(self, event):
        if self.labeling:
            if len(self.templabel) >= 4:
                self.label()
                self.status('标记错误,已重置', delay=800)
                return

            pointx = math.ceil(self.pmapShowAreaRect.getRect()[0] +
                               (self.pmapShowAreaRect.width() *
                                event.pos().x() / self.width()))
            pointy = math.ceil(self.pmapShowAreaRect.getRect()[1] +
                               (self.pmapShowAreaRect.height() *
                                event.pos().y() / self.height()))
            if self.pmapRect.contains(pointx, pointy):
                self.addTempPoint(pointx, pointy)
            else:
                self.status('请选择图片区域', delay=500)

    # 监听键盘ESC键按下
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            if self.labelQLabel:
                self.labelQLabel.hide()
            if self.labelEdit:
                self.labelEdit.hide()
            if self.templabel:
                self.templabel.clear()
            self.labeling = False
            self.repaint()

    def labelEditEnterPress(self):
        self.labelEdit.hide()
        if self.labelQLabel:
            self.labelQLabel.hide()

        labelText = self.labelEdit.text()
        templabelrect = [
            min(self.templabel[0], self.templabel[2]),
            min(self.templabel[1], self.templabel[3]),
            abs(self.templabel[0] - self.templabel[2]),
            abs(self.templabel[1] - self.templabel[3]),
            '默认标签名' if labelText.strip() == '' else labelText.strip()
        ]
        self.status('标签创建成功->' + str(templabelrect), delay=1000)
        self.labels.append(templabelrect)
        self.templabel.clear()
        self.labeling = False
        self.repaint()

    # 监听鼠标按下事件
    def mousePressEvent(self, event):
        if self.pmapShowAreaPreRect.contains(event.pos().x(), event.pos().y()):
            self.drag = True
        elif self.pmapPreRect.contains(event.pos().x(), event.pos().y()):
            pmapprerect = self.pmapPreRect.getRect()
            pmaprect = self.pmapRect.getRect()
            scale = pmaprect[2] / pmapprerect[2]
            ximage = (event.pos().x() - pmapprerect[0]) * scale
            yimage = (event.pos().y() - pmapprerect[1]) * scale
            self.pmapShowAreaRect.moveCenter(QPoint(ximage, yimage))
            self.repaint()
        else:
            self.labelTextClickCheck(event.pos().x(), event.pos().y())

    # 鼠标点击到标签逻辑
    def labelTextClickCheck(self, widgetx, widgety):
        for i in range(len(self.textRects)):
            if self.textRects[i].contains(widgetx, widgety):
                self.status(str(self.labels[i]), delay=1000)
                labelx, labely, labelwidth, labelheight = self.labels[i][:4]
                self.pmapShowAreaRect.moveCenter(
                    QRect(labelx, labely, labelwidth, labelheight).center())
                self.repaint()
                return

        for i in range(len(self.deleteRects)):
            if self.deleteRects[i].contains(widgetx, widgety):
                self.labels.pop(i)
                self.repaint()
                return

    # 鼠标移动事件
    def mouseMoveEvent(self, event):
        pointx = math.ceil(self.pmapShowAreaRect.getRect()[0] +
                           (self.pmapShowAreaRect.width() * event.pos().x() /
                            self.width()))
        pointy = math.ceil(self.pmapShowAreaRect.getRect()[1] +
                           (self.pmapShowAreaRect.height() * event.pos().y() /
                            self.height()))
        self.labelCoordinates.setText('X: %s Y: %s' % (pointx, pointy))

        if self.drag and self.dragAreaRect.contains(event.pos().x(),
                                                    event.pos().y()):
            pmapprerect = self.pmapPreRect.getRect()
            pmaprect = self.pmapRect.getRect()
            scale = pmaprect[2] / pmapprerect[2]
            ximage = (event.pos().x() - pmapprerect[0]) * scale
            yimage = (event.pos().y() - pmapprerect[1]) * scale
            self.pmapShowAreaRect.moveCenter(QPoint(ximage, yimage))
            self.repaint()
        else:
            if self.pmapPreRect.contains(event.pos().x(), event.pos().y()):
                self.mousex, self.mousey = 0, 0
                self.repaint()
            else:
                self.mousex, self.mousey = event.pos().x(), event.pos().y()
                self.repaint()

    def mouseReleaseEvent(self, event):
        self.drag = False

    # 以图片中心放大图片
    def enlargeByCenter(self):
        pmapshowarearect = self.pmapShowAreaRect.getRect()
        pmaprect = self.pmapRect.getRect()
        if pmapshowarearect[2] <= pmaprect[2] / 20 or pmapshowarearect[
                3] <= pmaprect[3] / 20:
            return

        self.pmapShowAreaRect.adjust(
            self.pmapShowAreaRect.width() * self.scaleRate,
            self.pmapShowAreaRect.height() * self.scaleRate,
            -self.pmapShowAreaRect.width() * self.scaleRate,
            -self.pmapShowAreaRect.height() * self.scaleRate)
        self.repaint()

    # 以图片中心缩放图片
    def narrowByCenter(self):
        pmapshowarearect = self.pmapShowAreaRect.getRect()
        pmaprect = self.pmapRect.getRect()
        if pmapshowarearect[2] >= pmaprect[2] or pmapshowarearect[
                3] >= pmaprect[3]:
            return

        self.pmapShowAreaRect.adjust(
            -self.pmapShowAreaRect.width() * self.scaleRate /
            (1 - 2 * self.scaleRate), -self.pmapShowAreaRect.height() *
            self.scaleRate / (1 - 2 * self.scaleRate),
            self.pmapShowAreaRect.width() * self.scaleRate /
            (1 - 2 * self.scaleRate),
            self.pmapShowAreaRect.height() * self.scaleRate /
            (1 - 2 * self.scaleRate))
        self.repaint()

    def statusLabel(self, message):
        if self.labelQLabel:
            self.labelQLabel.setText(message)

    def status(self, message, delay=-1):
        if self.statusbar:
            self.statusbar.showMessage(message, delay)

    def labelCoord(self, message):
        if self.labelCoordinates:
            self.labelCoordinates.setText(message)

    def setStatusBar(self, statusbar):
        self.statusbar = statusbar

    def setlabelCoordinates(self, labelCoordinates):
        self.labelCoordinates = labelCoordinates
示例#5
0
    def paintEvent(self, e):
        self.painter.begin(self)

        # 绘制图片内容
        self.painter.drawPixmap(self.rect(), self.pixmap,
                                self.pmapShowAreaRect)

        # 绘制图片区域预览
        self.painter.setPen(QColor(0, 0, 0))
        scale = min(self.width() / self.pixmap.width() / 5,
                    self.height() / self.pixmap.height() / 5)
        self.pmapPreRect = QRect(0, 0,
                                 self.pixmap.width() * scale,
                                 self.pixmap.height() * scale)
        margin = int(min(self.width(), self.height()) / 16)
        self.pmapPreRect.moveTopRight(QPoint(self.width() - margin, margin))
        self.painter.drawRect(self.pmapPreRect)

        # 绘制图片展示区域预览
        self.painter.setPen(QColor(255, 0, 0))
        pmapprerect = self.pmapPreRect.getRect()
        pmapshowarearect = self.pmapShowAreaRect.getRect()
        x = pmapprerect[0] + self.pmapPreRect.width(
        ) * pmapshowarearect[0] / self.pixmap.width()
        y = pmapprerect[1] + self.pmapPreRect.height(
        ) * pmapshowarearect[1] / self.pixmap.height()
        w = scale * self.pmapShowAreaRect.width()
        h = scale * self.pmapShowAreaRect.height()
        self.pmapShowAreaPreRect = QRect(x, y, w, h)
        self.painter.drawRect(self.pmapShowAreaPreRect)

        self.dragAreaRect = QRect(
            self.pmapPreRect.x() - self.pmapShowAreaPreRect.width(),
            self.pmapPreRect.y() - self.pmapShowAreaPreRect.height(),
            self.pmapShowAreaPreRect.width() + self.pmapPreRect.width(),
            self.pmapShowAreaPreRect.height() + self.pmapPreRect.height())

        # 绘制缩放中心点标线
        self.painter.setPen(QColor(255, 0, 0))
        self.painter.drawLine(self.width() / 3,
                              self.height() / 2,
                              self.width() / 3 * 2,
                              self.height() / 2)
        self.painter.drawLine(self.width() / 2,
                              self.height() / 3,
                              self.width() / 2,
                              self.height() / 3 * 2)

        # 绘制鼠标位置标线
        if self.labeling:
            self.painter.setPen(QColor(0, 0, 0))
            self.painter.drawLine(self.mousex, 0, self.mousex, self.height())
            self.painter.drawLine(0, self.mousey, self.width(), self.mousey)

        # 绘制正在编辑中的label位置
        if self.templabel:
            for i in range(int(len(self.templabel) / 2)):
                imagex, imagey = self.templabel[0 +
                                                2 * i], self.templabel[1 +
                                                                       2 * i]
                if self.pmapShowAreaRect.contains(imagex, imagey):
                    widgetx, widgety = self.imageXY2WidgetXY(imagex, imagey)
                    self.painter.setPen(QPen(Qt.red, 5))
                    self.painter.drawPoint(widgetx, widgety)

                    pen = QPen(Qt.black, 2, Qt.SolidLine)
                    pen.setStyle(Qt.DashDotDotLine)
                    self.painter.setPen(pen)
                    self.painter.drawLine(widgetx, 0, widgetx, self.height())
                    self.painter.drawLine(0, widgety, self.width(), widgety)

        # 绘制已标记内容
        self.deleteRects.clear()
        self.textRects.clear()

        self.painter.setPen(QColor(168, 34, 3))
        self.painter.setFont(QFont('Decorative', 12))
        metrics = self.painter.fontMetrics()
        deleteRectWidth, deleteRectHeight = metrics.height(
        ) * 1.2, metrics.height() * 1.2

        separatorheight = margin / 10

        pmapprerect = self.pmapPreRect.getRect()
        topRightx, topRighty = self.width(
        ) - margin, pmapprerect[1] + pmapprerect[3] + margin / 4
        for i in range(len(self.labels)):
            label = self.labels[i]
            # 绘制文字展示信息
            text = label[4]
            deleteRect = QRect(
                topRightx - deleteRectWidth,
                topRighty + (deleteRectHeight + separatorheight) * i,
                deleteRectWidth, deleteRectHeight)
            self.painter.drawRect(deleteRect)
            self.painter.drawLine(deleteRect.topLeft(),
                                  deleteRect.bottomRight())
            self.painter.drawLine(deleteRect.topRight(),
                                  deleteRect.bottomLeft())
            self.deleteRects.append(deleteRect)

            deleterect = deleteRect.getRect()
            textWidth, textHeight = metrics.width(text), metrics.height()
            textRect = QRect(deleterect[0] - textWidth - metrics.height(),
                             deleterect[1], textWidth + metrics.height(),
                             deleterect[3])
            self.painter.drawRect(textRect)
            self.painter.drawText(textRect, Qt.AlignCenter, text)
            self.textRects.append(textRect)
            # 在图片上绘制标签矩形框
            labelPixmapX, labelPixmapY, labelPixmapWidth, labelPixmapHeight = label[:
                                                                                    4]
            labelPixmapRect = QRect(labelPixmapX, labelPixmapY,
                                    labelPixmapWidth, labelPixmapHeight)
            intersectedRect = self.pmapShowAreaRect.intersected(
                labelPixmapRect)
            if intersectedRect:
                pixmapTopLeftPoint, pixmapBottomRightPoint = intersectedRect.topLeft(
                ), intersectedRect.bottomRight()
                widgetTopLeftPointX, widgetTopLeftPointY = self.imageXY2WidgetXY(
                    pixmapTopLeftPoint.x(), pixmapTopLeftPoint.y())
                widgetTopLeftPoint = QPoint(widgetTopLeftPointX,
                                            widgetTopLeftPointY)
                widgetBottomRightPointX, widgetBottomRightPointY = self.imageXY2WidgetXY(
                    pixmapBottomRightPoint.x(), pixmapBottomRightPoint.y())
                widgetBottomRightPoint = QPoint(widgetBottomRightPointX,
                                                widgetBottomRightPointY)
                labelRect = QRect(widgetTopLeftPoint, widgetBottomRightPoint)
                self.painter.drawRect(labelRect)
                # 绘制标签名
                labelrect = labelRect.getRect()
                textRect1 = QRect(labelrect[0], labelrect[1] - textHeight,
                                  textWidth, textHeight)
                # self.painter.drawRect(textRect1)
                self.painter.drawText(textRect1, Qt.AlignCenter, text)

        self.painter.end()
示例#6
0
class Ui_ScShot_Logic(QWidget, Ui_ScShot):
    """
    截屏逻辑:
    1、一打开截屏,就先创建屏幕截图pixScreenshot,并设置为主窗口的背景,并设置窗口无标题栏。再创建一个QWidget(wTop),
    用来作为全屏的阴影遮盖,设置背景样式rgba的透明,它的大小以及主窗口的大小都是全屏大小(和全屏截图一样大)。功能
    按钮容器wFunc,以及其它功能不作介绍,代码里有注释。
    2、设置鼠标按下、移动,释放,来画出一个矩形框。在移动的时候设置标记(flagDrawing)为True,并self.update刷新界面,在刷新
    界面时就能设置画笔和画刷来画出所要截图的范围
    3、这第三步,其实有一部分在第一处就要设置。这对我来说是个难点,研究了两天,才瞎猫碰到死耗子搞成了。原本在网上复制的
    截屏代码,竟然矩形选框内被穿透了,直接可以操作内部(此程序下面此范围内),很是让人无语。才研究两天,总算总算解决了。
    此程序就是用pyqt5的setMask遮罩效果来完成对我来说主要的功能的。
    在初始化处先创建一个QBitmap(blackMask),并填充成黑色,然后设置QWidget(wTop)的遮罩为blackMask。这里简单说一下,如果
    在遮罩的地方用白色画刷涂的地方会失去遮罩(也就是wTop的背景),显示出下层窗口(窗口已经设置为全屏截图)的图片。
    用黑色画刷涂的话,就是显示出wTop的背景。这里就样photoShop中的那个蒙版效果,原理是一样的。重要处在paintEvent事件中,
    已经有注释。
    """

    def __init__(self, parent):
        super(Ui_ScShot_Logic, self).__init__()
        self.setupUi(self) # 加载设计师画的界面
        self.p = parent

        # 主窗口设置
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)  # 隐藏标题栏
        self.pixPrtSc = QApplication.primaryScreen().grabWindow(QApplication.desktop().winId())  # 截取整个屏幕(QPixmap类型)
        self.resize(self.pixPrtSc.size())  # 设置主窗口大小
        p = QPalette()
        p.setBrush(self.backgroundRole(), QBrush(self.pixPrtSc))
        self.setPalette(p)  # 设置主窗口背景
        self.flagDrawing = False  # 主窗口的鼠标拖动标记,已经为子

        self.wid = QLabel(self)
        self.wid.lower()
        # self.wid.raise_() # 最上层
        self.wid.resize(self.size())
        self.wid.move(0, 0)
        self.wid.setStyleSheet('border:3px solid #00FFFF;')
        # self.wid.hide()


        # 阴影容器设置
        self.wTop.resize(self.size())  # 设置wTop也为屏幕大小
        self.blackMask = QBitmap(self.size())  # 创建位图,全屏大小
        self.blackMask.fill(Qt.black)  # 填充位图为全黑。显示效果为原本wTop的背影,如果全白,相当于把wTop擦掉了。
        self.wTop.setMask(self.blackMask)  # 设置self.wTop的遮罩为self.blackMask
        self.wTop.enterEvent = self.wTop_EnterEvent  # 设置wTop的鼠标进入事件。事件内有详细注释。
        self.flagWTopEnter = False  # wTop的鼠标进入事件的标记

        # 其它需要初始化的
        self.btnOk.clicked.connect(self.slot_ScShot_btns)
        self.btnSaveAs.clicked.connect(self.slot_ScShot_btns)
        self.wFunc.hide()  # 先隐藏功能按钮容器
        self.wInfo.hide() # 本来可以不用隐藏,再让后面显示,但是那样它会闪一下。因为原来的位置是在Qt设计师中乱放的。
        self.strDpi = "0 x 0"
        self.flag = False

        # lab = QLabel('aaa', self.wTop)
        # lab.resize(300, 300)
        # lab.setStyleSheet('background:red;')

    def wTop_EnterEvent(self, e):
        """
        鼠标进入wTop子QWidget内,为了处理一打开截屏界面wInfo初始跟随鼠标状态,只需要一次,因为有self的鼠标
        mouseMoveEvent处理后续动作。之所以要做一个标记flagWTopEnter为False才有动作,是因为在截图时,画的矩形
        选区内是self的焦点,之外才是wTop的焦点。鼠标在矩形内外来回移动会多次处理此事件动作,关键是此动作和
        self的鼠标移动件事有冲突,都在处理wInfo的鼠标跟随。目前只想到这种方法解决。
        """
        if not self.flagWTopEnter:  # 只有self.flagWTopEnter=False时,not self.flagWTopEnter 才为真
            self.flagWTopEnter = True
            self.imgPrtSc = self.pixPrtSc.toImage()
            self.method_wInfo(e.globalPos().x(), e.globalPos().y())
            self.wInfo.show()
            # rect = QRect(e.globalPos().x() - 13, e.globalPos().y() - 10, 114, 85)  # 截取的范围
            # copyZoomIn = self.pixPrtSc.copy(rect)
            # self.labInfoZoomIn.setPixmap(copyZoomIn)

    def method_wInfo(self, pointX, pointY):
        """QWidget(wInfo)的移动,以及wInfo内的QLebal(labInfoZoomIn)的图片设置"""
        self.wInfo.move(pointX + 5, pointY + 20)
        color = self.imgPrtSc.pixelColor(pointX, pointY)
        self.strRgb = str(color.getRgb()[:-1])
        self.textEdInfoRgb.setText(f"DPI:({self.strDpi})<br/>RGB:{self.strRgb}")  # 13 10
        # 参数32,24,是矩形的宽高,是要QLabel(labInfoZoomIn)设置的图片,因为在设计师中已经设置setScaledContents为True,
        # 所以它放比它小的图片会放大。而pointX-14和pointY-10,是矩形的左上角位置,需要减多少,是看原图大小的宽高除以2,
        # 再减去十字线(宽4px)的一半(32/2-2=14,24/2-2=10。labInfoZoomIn的尺寸是116x84
        # 这样,labInfoZoomIn在显示图片的时候,十字交差处才会是鼠标指针点的位置。
        rect = QRect(pointX-14, pointY-10, 32, 24)  # 截取的范围
        copyZoomIn = self.pixPrtSc.copy(rect)
        self.labInfoZoomIn.setPixmap(copyZoomIn)

    def slot_ScShot_btns(self):
        sender = self.sender()
        filePath = self.p.lineEdFilePath.text()
        rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
        self.copyPixPrtSc = self.pixPrtSc.copy(self.rect)  # 截取矩形区内的图片
        PlaySound('prtSc.wav', flags=1)
        if sender == self.btnOk:
            if not os.path.exists(filePath):  # 如果此路径没有此文件夹,就创建一个
                os.mkdir(filePath)
            imgPath = f"{filePath}/{rq}.png"
            self.copyPixPrtSc.save(imgPath, format='png', quality=100)
        elif sender == self.btnSaveAs:
            currentPath = filePath + f"/{rq}.png"
            fileName, _ = QFileDialog.getSaveFileName(self, "另存为", currentPath, f"PNG File(*.png);;All Files(*)")
            if fileName:
                self.copyPixPrtSc.save(fileName, format='png', quality=100)
                self.close()

    def paintEvent(self, event):
        if self.flag:
            pointX = self.endPoint.x()
            pointY = self.endPoint.y()
            self.method_wInfo(pointX, pointY)  # 调用移动方法

        if self.flagDrawing:
            self.mask = self.blackMask.copy()  # 必须要拷贝,其实我也不是很理解这句为何。
            pp = QPainter(self.mask)  # 参数一定要是拷贝的QPixmap(self.mask)
            pen = QPen()  # 创建画笔    Qt.green, 13, Qt.DashDotLine, Qt.RoundCap, Qt.RoundJoin
            pen.setStyle(Qt.NoPen)
            pp.setPen(pen)
            brush = QBrush(Qt.white)  # 创建画刷
            pp.setBrush(brush)
            rect = QRect(self.startPoint, self.endPoint)
            pp.drawRect(rect)  # 画矩形
            self.wTop.setMask(QBitmap(self.mask))  # 是wTop设置遮罩,不是主窗口。不然会穿透的。

            self.strDpi = f"{abs(rect.width())} x {abs(rect.height())}"
            # self.wid.setStyleSheet('border:2px dashed #00FFFF;') # 改变边宽和样式(虚线)
            # self.wid.setGeometry(rect.adjusted(-2, -2, 2, 2)) # 上下左右都往外偏移2px,因为上面设置border为2px
            # self.wid.setGeometry( rect.x()-2, rect.y()-2,abs(rect.width())+2,abs(rect.height())+2) # 上下左右都往外偏移2px,因为上面设置border为2px
            try:
                sX, sY, eX, eY = self.startPoint.x(), self.startPoint.y(), self.endPoint.x(), self.endPoint.y()
                p2 = QPainter(self)
                pen2 = QPen(QColor('#00FFFF'), 1)
                p2.setPen(pen2)
                p2.drawRect(rect)
                # 下面这四句忘了本来要做什么的了
                # p2.fillRect(rect, QColor('background:rgba(0,0,0,100);'))
                # rect.adjust(50, 50, -50, -50)
                # p2.drawRect(rect)
                # p2.fillRect(rect, Qt.red)


                listPointRect = [(sX, sY), (sX + (eX - sX) / 2, sY), (eX, sY), (eX, sY + (eY - sY) / 2),
                                 (eX, eY), (sX + (eX - sX) / 2, eY), (sX, eY), (sX, sY + (eY - sY) / 2)]
                for x, y in listPointRect:
                    p2.drawRect(x - 3, y - 3, 6, 6)
                    p2.fillRect(x - 3, y - 3, 6, 6, QBrush(QColor('#00FFFF')))


                # p2.begin(self)
                # path = QPainterPath()
                # path.addRect(QRectF(self.startPoint, self.endPoint))

                # self.wid.setGeometry(QRect(*path.controlPointRect().getRect()).adjusted(-20, -20, 20, 20))
                # p2.drawRect(QRectF(*(sX, sY), *(sX + (eX - sX) / 2, sY)))



                # listPointRect = [(sX, sY), (sX+(eX-sX)/2, sY), (eX, sY), (eX, sY+(eY-sY)/2),
                #                  (eX, eY), (sX+(eX-sX)/2, eY), (sX, eY), (sX, sY+(eY-sY)/2)]
                # path2 = QPainterPath()
                # for x, y in listPointRect:
                #     path2.addRect(x-3, y-3, 6, 6)
                # p2.fillPath(path2, QBrush(QColor('#00FFFF')))
                # path.connectPath(path2) # 连接两个闭合路径
                # path.translate(50, 50) # 偏移到某点
                # p2.drawPath(path)
                # self.wid.setStyleSheet('border:none;')
                # p2.end()

            except Exception as e:
                print(e)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            # self.wid.hide()
            self.wTop.setStyleSheet('background:rgba(0,0,0,100);') # 设置背景透明度,阴影效果。鼠标按下时再出现
            self.wInfo.show()
            self.startPoint = event.pos()
            self.endPoint = self.startPoint
            self.wFunc.hide()  # 鼠标按下时隐藏功能按钮容器
            self.flagDrawing = True
        elif event.button() == Qt.RightButton:
            self.close()

    def mouseMoveEvent(self, event):
        """
        必须为子控件设置鼠标跟踪setMouseTracking(True),不然鼠标在控件上时,就不再追踪了。
        已经在Qt设计师中设置好了
        """
        self.flag = True
        self.endPoint = event.pos()
        self.update()

        # self.pointX = event.globalPos().x()  # event.pos()也行
        # self.pointY = event.globalPos().y()
        # self.flag = True
        # # self.method_wInfo_move(pointX, pointY)  # 调用移动方法
        # if self.flagDrawing:
        #     self.endPoint = event.pos()
        # self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.endPoint = event.pos()
            self.rect = QRect(self.startPoint, self.endPoint)  # 截取的范围
            shotX, shotY, shotWidth, shotHeight = self.rect.getRect()
            wFuncWidth, wFuncHeight = self.wFunc.width(), self.wFunc.height()
            # 以下if语句是判断鼠标释放后,最后一点到窗口边缘时,功能按钮容器超界问题
            if shotWidth < 0:
                moveX = shotX + shotWidth - (wFuncWidth + shotWidth)  # 这里width是负数,这里用+号相当于减去
            else:
                moveX = shotX + shotWidth - wFuncWidth
            if shotHeight < 0:
                moveY = shotY
            else:
                moveY = shotY + shotHeight
            if moveX < 0:
                moveX = 0
            if self.pixPrtSc.height() - moveY < wFuncHeight:
                moveY = moveY - shotHeight - wFuncHeight
            self.wFunc.move(moveX, moveY)
            self.wFunc.show() # 鼠标释放时显示功能按钮容器
            self.wInfo.hide() # 鼠标释放时隐藏信息显示容器
            self.flagDrawing = False
            self.flag = False #

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.close()