예제 #1
0
class ResizableRubberBand(QWidget):
    """ provides a rectangle which is defined by click and drag with the mouse and can be resized
    afterwards
    """
    def __init__(self, parent=None):
        super(ResizableRubberBand, self).__init__(parent)
        self.setWindowFlag(Qt.SubWindow)
        self.setFocusPolicy(Qt.ClickFocus)
        self.layout = QHBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setCursor(Qt.SizeAllCursor)
        self.origin = QPoint()

        self.grip1 = QSizeGrip(self)
        self.grip2 = QSizeGrip(self)
        self.layout.addWidget(self.grip1, 0, Qt.AlignLeft | Qt.AlignTop)
        self.layout.addWidget(self.grip2, 0, Qt.AlignRight | Qt.AlignBottom)

        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)

        self.rubberband.move(0, 0)
        self.hide()
        self.rubberband.hide()
        # self.rubberband.show()
        # self.show()

    def resizeEvent(self, event):
        self.rubberband.resize(self.size())

    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QPainter(self)
        painter.beginNativePainting()
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        painter.setPen(QPen(Qt.red, 3))
        painter.drawRect(self.rubberband.rect())
        painter.setPen(QPen(Qt.red, 1))
        x_begin = self.rubberband.x()
        x_half = self.rubberband.x() + self.rubberband.width() / 2
        x_full = self.rubberband.x() + self.rubberband.width()
        y_begin = self.rubberband.y()
        y_half = self.rubberband.y() + self.rubberband.height() / 2
        y_full = self.rubberband.y() + self.rubberband.height()
        points = [
            QPoint(x_half, y_begin),
            QPoint(x_half, y_full),
            QPoint(x_begin, y_half),
            QPoint(x_full, y_half)
        ]
        painter.drawLines(points)
        painter.endNativePainting()
        painter.end()

    # def moveEvent(self, event: QMoveEvent):
    #     self.rubberband.move(event.pos())

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.origin = event.globalPos() - self.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() - self.origin)
예제 #2
0
class DynamicNeedleMask(QWidget):
    """ 
    provides a rectangle with fixed centerline and x-symmetric resizability
    """
    _gripSize = 8
    update_mask_signal = Signal()

    def __init__(self, parent=None):
        super(DynamicNeedleMask, self).__init__(parent)
        self.settings = QSettings()
        self._first_show = True
        self.setWindowFlag(Qt.SubWindow)
        self.setFocusPolicy(Qt.ClickFocus)
        self.layout = QHBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setCursor(Qt.SizeAllCursor)
        self.setGeometry(self.parent().width() / 2 - 10, 0, 20,
                         self.parent().height())
        self._old_geo = self.geometry()
        self._locked = False
        self.origin = QPoint(0, 0)
        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)

        self.rubberband.move(0, 0)
        self.hide()
        self.rubberband.hide()
        # self.rubberband.show()
        # self.show()
        self.sideGrips = [
            SideGrip(self, Qt.LeftEdge),
            SideGrip(self, Qt.TopEdge),
            SideGrip(self, Qt.RightEdge),
            SideGrip(self, Qt.BottomEdge),
        ]
        # corner grips should be "on top" of everything, otherwise the side grips
        # will take precedence on mouse events, so we are adding them *after*;
        # alternatively, widget.raise_() can be used
        self.cornerGrips = [QSizeGrip(self) for i in range(4)]

    def get_mask_geometry(self) -> Tuple[int, int, int, int]:
        """Return the geometry of the mask

        :returns: the geometry of the mask as x,y,w,h tuple
        """
        return self.geometry().normalized().getRect()

    def lock(self):
        """lock resizing
        """
        self._locked = True

    def unlock(self):
        """unlock resizing
        """
        self._locked = False

    def showEvent(self, event):
        """
        custom show event

        initializes geometry for first show
        """
        if self._first_show:
            geo = self.load_geo()
            if geo:
                self.setGeometry(*geo)
            else:
                self.setGeometry(self.parent().width() * 15 / 32, 0,
                                 self.parent().width() / 16,
                                 self.parent().height())
            self._first_show = False

    @property
    def gripSize(self):
        return self._gripSize

    def setGripSize(self, size):
        if size == self._gripSize:
            return
        self._gripSize = max(2, size)
        self.updateGrips()

    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QPainter(self)
        painter.beginNativePainting()
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        painter.setPen(QPen(Qt.green, 1, Qt.DotLine))
        painter.drawRect(self.rubberband.rect())
        painter.setPen(QPen(Qt.green, 1))
        x_begin = self.rubberband.x()
        x_half = self.rubberband.x() + self.rubberband.width() / 2
        x_full = self.rubberband.x() + self.rubberband.width()
        y_begin = self.rubberband.y()
        y_half = self.rubberband.y() + self.rubberband.height() / 2
        y_full = self.rubberband.y() + self.rubberband.height()
        points = [QPoint(x_half, y_begin), QPoint(x_half, y_full)]
        painter.drawLines(points)
        painter.endNativePainting()
        painter.end()

    def resizeEvent(self, event: QResizeEvent):
        x, y, w, h = self.geometry().normalized().getRect()

        if (self._locked):
            self.setGeometry(*self._old_geo.getRect())
        else:
            # limit size to parent boundaries
            if (x < 0):
                # remove width that has been added by leftward dragging if x is at leftmost edge
                w += x
            x = max(0, min(x, self.parent().width()))
            w = min(w, self.parent().width() - x)

            self.setGeometry(x, y, w, self.parent().height())
            self.updateGrips()
            self.rubberband.resize(self.size())
            self._old_geo = self.geometry()
            self.update_mask_signal.emit()

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.origin = event.globalPos() - self.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            x, y, w, h = self.geometry().normalized().getRect()
            new_x = event.globalPos().x() - self.origin.x()
            # keep inside parent boundaries
            new_x = max(0, min(new_x, self.parent().width() - w))
            self.move(new_x, 0)
            self.update_mask_signal.emit()

    def mouseReleaseEvent(self, event):
        self.update_mask_signal.emit()
        self.save_geo()
        return super().mouseReleaseEvent(event)

    def save_geo(self):
        self.settings.setValue("needle_mask/geometry",
                               self.geometry().getRect())

    def load_geo(self):
        return self.settings.value("needle_mask/geometry")

    def updateGrips(self):
        self.setContentsMargins(*[self.gripSize] * 4)

        outRect = self.rect()
        # an "inner" rect used for reference to set the geometries of size grips
        inRect = outRect.adjusted(self.gripSize, self.gripSize, -self.gripSize,
                                  -self.gripSize)

        # top left
        self.cornerGrips[0].setGeometry(
            QRect(outRect.topLeft(), inRect.topLeft()))
        # top right
        self.cornerGrips[1].setGeometry(
            QRect(outRect.topRight(), inRect.topRight()).normalized())
        # bottom right
        self.cornerGrips[2].setGeometry(
            QRect(inRect.bottomRight(), outRect.bottomRight()))
        # bottom left
        self.cornerGrips[3].setGeometry(
            QRect(outRect.bottomLeft(), inRect.bottomLeft()).normalized())

        # left edge
        self.sideGrips[0].setGeometry(0, inRect.top(), self.gripSize,
                                      inRect.height())
        # top edge
        self.sideGrips[1].setGeometry(inRect.left(), 0, inRect.width(),
                                      self.gripSize)
        # right edge
        self.sideGrips[2].setGeometry(inRect.left() + inRect.width(),
                                      inRect.top(), self.gripSize,
                                      inRect.height())
        # bottom edge
        self.sideGrips[3].setGeometry(self.gripSize,
                                      inRect.top() + inRect.height(),
                                      inRect.width(), self.gripSize)