【问题标题】:Resize a QGraphicsItem with the mouse用鼠标调整 QGraphicsItem 的大小
【发布时间】:2015-12-23 06:09:23
【问题描述】:

在将rectangle 放入QGraphicsScene 并使用鼠标使其可移动后,如何使用鼠标调整其大小?

如果没有人知道答案,也可以举个例子,我正在使用PyQt4 在 Python 中进行开发。

我知道这里有类似的问题,但他们没有分别回答我。

我的简化代码:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

app = QApplication(sys.argv)

grview = QGraphicsView()
scene = QGraphicsScene()
scene.setSceneRect(0, 0, 512, 512)

scene.addPixmap(QPixmap('01.png'))
grview.setScene(scene)

item = QGraphicsRectItem(0, 0, 300, 150)

pen = QPen(Qt.darkMagenta)
pen.setWidth(4)
item.setPen(pen)

item.setFlag(QGraphicsItem.ItemIsMovable)
scene.addItem(item)

grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)

grview.show()

sys.exit(app.exec_())

【问题讨论】:

    标签: python qt pyqt


    【解决方案1】:

    您需要自己实施调整大小。为此,您需要继承 QGraphicsRectItem 并实现鼠标事件处理程序:mousePressEventmouseMoveEventmouseReleaseEvent。 大致思路如下:

    • 您创建一组可用于调整形状大小的手柄。
    • 通过跟踪手柄位置变化,您可以计算出新的几何形状。

    我之前写了一些代码,它可以完美地与 PyQt5 一起使用,但它也应该可以与 PyQt4 一起使用。您应该能够根据需要对其进行调整:

    import sys
    
    from PyQt5.QtCore import Qt, QRectF, QPointF
    from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen, QPixmap
    from PyQt5.QtWidgets import QGraphicsRectItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
    
    
    class GraphicsRectItem(QGraphicsRectItem):
    
        handleTopLeft = 1
        handleTopMiddle = 2
        handleTopRight = 3
        handleMiddleLeft = 4
        handleMiddleRight = 5
        handleBottomLeft = 6
        handleBottomMiddle = 7
        handleBottomRight = 8
    
        handleSize = +8.0
        handleSpace = -4.0
    
        handleCursors = {
            handleTopLeft: Qt.SizeFDiagCursor,
            handleTopMiddle: Qt.SizeVerCursor,
            handleTopRight: Qt.SizeBDiagCursor,
            handleMiddleLeft: Qt.SizeHorCursor,
            handleMiddleRight: Qt.SizeHorCursor,
            handleBottomLeft: Qt.SizeBDiagCursor,
            handleBottomMiddle: Qt.SizeVerCursor,
            handleBottomRight: Qt.SizeFDiagCursor,
        }
    
        def __init__(self, *args):
            """
            Initialize the shape.
            """
            super().__init__(*args)
            self.handles = {}
            self.handleSelected = None
            self.mousePressPos = None
            self.mousePressRect = None
            self.setAcceptHoverEvents(True)
            self.setFlag(QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QGraphicsItem.ItemIsSelectable, True)
            self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
            self.setFlag(QGraphicsItem.ItemIsFocusable, True)
            self.updateHandlesPos()
    
        def handleAt(self, point):
            """
            Returns the resize handle below the given point.
            """
            for k, v, in self.handles.items():
                if v.contains(point):
                    return k
            return None
    
        def hoverMoveEvent(self, moveEvent):
            """
            Executed when the mouse moves over the shape (NOT PRESSED).
            """
            if self.isSelected():
                handle = self.handleAt(moveEvent.pos())
                cursor = Qt.ArrowCursor if handle is None else self.handleCursors[handle]
                self.setCursor(cursor)
            super().hoverMoveEvent(moveEvent)
    
        def hoverLeaveEvent(self, moveEvent):
            """
            Executed when the mouse leaves the shape (NOT PRESSED).
            """
            self.setCursor(Qt.ArrowCursor)
            super().hoverLeaveEvent(moveEvent)
    
        def mousePressEvent(self, mouseEvent):
            """
            Executed when the mouse is pressed on the item.
            """
            self.handleSelected = self.handleAt(mouseEvent.pos())
            if self.handleSelected:
                self.mousePressPos = mouseEvent.pos()
                self.mousePressRect = self.boundingRect()
            super().mousePressEvent(mouseEvent)
    
        def mouseMoveEvent(self, mouseEvent):
            """
            Executed when the mouse is being moved over the item while being pressed.
            """
            if self.handleSelected is not None:
                self.interactiveResize(mouseEvent.pos())
            else:
                super().mouseMoveEvent(mouseEvent)
    
        def mouseReleaseEvent(self, mouseEvent):
            """
            Executed when the mouse is released from the item.
            """
            super().mouseReleaseEvent(mouseEvent)
            self.handleSelected = None
            self.mousePressPos = None
            self.mousePressRect = None
            self.update()
    
        def boundingRect(self):
            """
            Returns the bounding rect of the shape (including the resize handles).
            """
            o = self.handleSize + self.handleSpace
            return self.rect().adjusted(-o, -o, o, o)
    
        def updateHandlesPos(self):
            """
            Update current resize handles according to the shape size and position.
            """
            s = self.handleSize
            b = self.boundingRect()
            self.handles[self.handleTopLeft] = QRectF(b.left(), b.top(), s, s)
            self.handles[self.handleTopMiddle] = QRectF(b.center().x() - s / 2, b.top(), s, s)
            self.handles[self.handleTopRight] = QRectF(b.right() - s, b.top(), s, s)
            self.handles[self.handleMiddleLeft] = QRectF(b.left(), b.center().y() - s / 2, s, s)
            self.handles[self.handleMiddleRight] = QRectF(b.right() - s, b.center().y() - s / 2, s, s)
            self.handles[self.handleBottomLeft] = QRectF(b.left(), b.bottom() - s, s, s)
            self.handles[self.handleBottomMiddle] = QRectF(b.center().x() - s / 2, b.bottom() - s, s, s)
            self.handles[self.handleBottomRight] = QRectF(b.right() - s, b.bottom() - s, s, s)
    
        def interactiveResize(self, mousePos):
            """
            Perform shape interactive resize.
            """
            offset = self.handleSize + self.handleSpace
            boundingRect = self.boundingRect()
            rect = self.rect()
            diff = QPointF(0, 0)
    
            self.prepareGeometryChange()
    
            if self.handleSelected == self.handleTopLeft:
    
                fromX = self.mousePressRect.left()
                fromY = self.mousePressRect.top()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setX(toX - fromX)
                diff.setY(toY - fromY)
                boundingRect.setLeft(toX)
                boundingRect.setTop(toY)
                rect.setLeft(boundingRect.left() + offset)
                rect.setTop(boundingRect.top() + offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleTopMiddle:
    
                fromY = self.mousePressRect.top()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setY(toY - fromY)
                boundingRect.setTop(toY)
                rect.setTop(boundingRect.top() + offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleTopRight:
    
                fromX = self.mousePressRect.right()
                fromY = self.mousePressRect.top()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setX(toX - fromX)
                diff.setY(toY - fromY)
                boundingRect.setRight(toX)
                boundingRect.setTop(toY)
                rect.setRight(boundingRect.right() - offset)
                rect.setTop(boundingRect.top() + offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleMiddleLeft:
    
                fromX = self.mousePressRect.left()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                diff.setX(toX - fromX)
                boundingRect.setLeft(toX)
                rect.setLeft(boundingRect.left() + offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleMiddleRight:
                print("MR")
                fromX = self.mousePressRect.right()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                diff.setX(toX - fromX)
                boundingRect.setRight(toX)
                rect.setRight(boundingRect.right() - offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleBottomLeft:
    
                fromX = self.mousePressRect.left()
                fromY = self.mousePressRect.bottom()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setX(toX - fromX)
                diff.setY(toY - fromY)
                boundingRect.setLeft(toX)
                boundingRect.setBottom(toY)
                rect.setLeft(boundingRect.left() + offset)
                rect.setBottom(boundingRect.bottom() - offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleBottomMiddle:
    
                fromY = self.mousePressRect.bottom()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setY(toY - fromY)
                boundingRect.setBottom(toY)
                rect.setBottom(boundingRect.bottom() - offset)
                self.setRect(rect)
    
            elif self.handleSelected == self.handleBottomRight:
    
                fromX = self.mousePressRect.right()
                fromY = self.mousePressRect.bottom()
                toX = fromX + mousePos.x() - self.mousePressPos.x()
                toY = fromY + mousePos.y() - self.mousePressPos.y()
                diff.setX(toX - fromX)
                diff.setY(toY - fromY)
                boundingRect.setRight(toX)
                boundingRect.setBottom(toY)
                rect.setRight(boundingRect.right() - offset)
                rect.setBottom(boundingRect.bottom() - offset)
                self.setRect(rect)
    
            self.updateHandlesPos()
    
        def shape(self):
            """
            Returns the shape of this item as a QPainterPath in local coordinates.
            """
            path = QPainterPath()
            path.addRect(self.rect())
            if self.isSelected():
                for shape in self.handles.values():
                    path.addEllipse(shape)
            return path
    
        def paint(self, painter, option, widget=None):
            """
            Paint the node in the graphic view.
            """
            painter.setBrush(QBrush(QColor(255, 0, 0, 100)))
            painter.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
            painter.drawRect(self.rect())
    
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QBrush(QColor(255, 0, 0, 255)))
            painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            for handle, rect in self.handles.items():
                if self.handleSelected is None or handle == self.handleSelected:
                    painter.drawEllipse(rect)
    
    
    def main():
    
        app = QApplication(sys.argv)
    
        grview = QGraphicsView()
        scene = QGraphicsScene()
        scene.setSceneRect(0, 0, 680, 459)
    
        scene.addPixmap(QPixmap('01.png'))
        grview.setScene(scene)
    
        item = GraphicsRectItem(0, 0, 300, 150)
        scene.addItem(item)
    
        grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
        grview.show()
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 我收到此错误AttributeError: 'NoneType' object has no attribute 'right'
    • 发布回溯会有所帮助。无论如何,我编辑了代码,它现在应该可以工作了。
    • 我在 PyQt5 和 PyQt4 中尝试过你的代码,但还是不行。
    • 您应该提供回溯或更好地描述什么不起作用,因为对我来说它工作得很好。显然,您需要使代码适应您的特定环境。
    • 无法移动,所以在构造函数中添加了self.setFlags(QGraphicsItem.ItemIsMovable),但是无法调整大小,代码也不会产生错误。你能提供你如何使用的代码吗?因为我不明白它是如何在这里不起作用的。我真的需要这个功能。
    【解决方案2】:

    我也试图做类似的任务,除了在我的情况下,我需要一个可以继承需要调整大小的父项的可重用对象。下面是一个使用 Resizer 类将调整大小锚点添加到其父 QGraphicsRectItem 的示例。

    Resizer 类继承 QGraphicsObject 并重新实现了paint方法。 ResizeritemChange 方法发出一个信号,该信号分配给父 Box 类中的 resize 方法。这反过来使用来自调整大小的位置变化信息来调整框的矩形。

    这样,调整大小也可以重新用于其他项目,而无需重新实现鼠标按下/移动/释放事件。

    import sys
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    class Box(QGraphicsRectItem):
    
        def __init__(self, position, rect=QRectF(0, 0, 100, 50), parent=None, scene=None):
            super().__init__(rect, parent, scene)
    
            self.setFlag(QGraphicsItem.ItemIsSelectable, True)
            self.setFlag(QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QGraphicsItem.ItemIsFocusable, True)
            self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
    
            self.setPos(position)
    
            self.resizer = Resizer(parent=self)
            resizerWidth = self.resizer.rect.width() / 2
            resizerOffset = QPointF(resizerWidth, resizerWidth)
            self.resizer.setPos(self.rect().bottomRight() - resizerOffset)
            self.resizer.resizeSignal.connect(self.resize)
    
        def paint(self, painter, option, widget=None):
            pen = QPen()
            pen.setColor(Qt.black)
            painter.setPen(pen)
            painter.setBrush(Qt.transparent)
            painter.drawRect(self.rect())
    
        @pyqtSlot()
        def resize(self, change):
            self.setRect(self.rect().adjusted(0, 0, change.x(), change.y()))
            self.prepareGeometryChange()
            self.update()
    
    
    class Resizer(QGraphicsObject):
    
        resizeSignal = pyqtSignal(QPointF)
    
        def __init__(self, rect=QRectF(0, 0, 10, 10), parent=None):
            super().__init__(parent)
    
            self.setFlag(QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QGraphicsItem.ItemIsSelectable, True)
            self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
            self.rect = rect
    
        def boundingRect(self):
            return self.rect
    
        def paint(self, painter, option, widget=None):
            if self.isSelected():
                pen = QPen()
                pen.setStyle(Qt.DotLine)
                painter.setPen(pen)
            painter.drawEllipse(self.rect)
    
        def itemChange(self, change, value):
            if change == QGraphicsItem.ItemPositionChange:
                if self.isSelected():
                    self.resizeSignal.emit(value - self.pos())
            return value
    
    
    if __name__ == "__main__":
    
        app = QApplication(sys.argv)
    
        view = QGraphicsView()
        scene = QGraphicsScene()
        scene.setSceneRect(0, 0, 500, 1000)
        view.setScene(scene)
    
        box = Box(QPointF(50, 50), scene=scene)
    
        view.show()
    
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案3】:

      Daniele's code 非常有帮助,我特别喜欢调整大小的手柄。我不喜欢你可以将矩形移动到窗口限制之外或调整它的大小直到它具有负宽度或高度。

      此代码强制限制移动和调整大小,因此您不会导致这些问题。为了让这个例子简单,我放弃了调整大小的句柄。

      import typing
      
      from PySide6.QtCore import QRectF, QSize
      from PySide6.QtGui import QPen, QBrush, QColor, QResizeEvent
      from PySide6.QtWidgets import (QApplication, QGraphicsView, QGraphicsScene,
                                     QGraphicsItem, QGraphicsRectItem, QMainWindow,
                                     QVBoxLayout, QWidget)
      
      
      class ResizableRect(QGraphicsRectItem):
          def __init__(self, *args):
              super().__init__(*args)
              self.setFlag(QGraphicsItem.ItemIsMovable, True)
              self.setPen(QPen(QBrush(QColor('blue')), 5))
              self.selected_edge = None
              self.click_pos = self.click_rect = None
      
          def mousePressEvent(self, event):
              """ The mouse is pressed, start tracking movement. """
              self.click_pos = event.pos()
              rect = self.rect()
              if abs(rect.left() - self.click_pos.x()) < 5:
                  self.selected_edge = 'left'
              elif abs(rect.right() - self.click_pos.x()) < 5:
                  self.selected_edge = 'right'
              elif abs(rect.top() - self.click_pos.y()) < 5:
                  self.selected_edge = 'top'
              elif abs(rect.bottom() - self.click_pos.y()) < 5:
                  self.selected_edge = 'bottom'
              else:
                  self.selected_edge = None
              self.click_pos = event.pos()
              self.click_rect = rect
              super().mousePressEvent(event)
      
          def mouseMoveEvent(self, event):
              """ Continue tracking movement while the mouse is pressed. """
              # Calculate how much the mouse has moved since the click.
              pos = event.pos()
              x_diff = pos.x() - self.click_pos.x()
              y_diff = pos.y() - self.click_pos.y()
      
              # Start with the rectangle as it was when clicked.
              rect = QRectF(self.click_rect)
      
              # Then adjust by the distance the mouse moved.
              if self.selected_edge is None:
                  rect.translate(x_diff, y_diff)
              elif self.selected_edge == 'top':
                  rect.adjust(0, y_diff, 0, 0)
              elif self.selected_edge == 'left':
                  rect.adjust(x_diff, 0, 0, 0)
              elif self.selected_edge == 'bottom':
                  rect.adjust(0, 0, 0, y_diff)
              elif self.selected_edge == 'right':
                  rect.adjust(0, 0, x_diff, 0)
      
              # Figure out the limits of movement. I did it by updating the scene's
              # rect after the window resizes.
              scene_rect = self.scene().sceneRect()
              view_left = scene_rect.left()
              view_top = scene_rect.top()
              view_right = scene_rect.right()
              view_bottom = scene_rect.bottom()
      
              # Next, check if the rectangle has been dragged out of bounds.
              if rect.top() < view_top:
                  if self.selected_edge is None:
                      rect.translate(0, view_top-rect.top())
                  else:
                      rect.setTop(view_top)
              if rect.left() < view_left:
                  if self.selected_edge is None:
                      rect.translate(view_left-rect.left(), 0)
                  else:
                      rect.setLeft(view_left)
              if view_bottom < rect.bottom():
                  if self.selected_edge is None:
                      rect.translate(0, view_bottom - rect.bottom())
                  else:
                      rect.setBottom(view_bottom)
              if view_right < rect.right():
                  if self.selected_edge is None:
                      rect.translate(view_right - rect.right(), 0)
                  else:
                      rect.setRight(view_right)
      
              # Also check if the rectangle has been dragged inside out.
              if rect.width() < 5:
                  if self.selected_edge == 'left':
                      rect.setLeft(rect.right() - 5)
                  else:
                      rect.setRight(rect.left() + 5)
              if rect.height() < 5:
                  if self.selected_edge == 'top':
                      rect.setTop(rect.bottom() - 5)
                  else:
                      rect.setBottom(rect.top() + 5)
      
              # Finally, update the rect that is now guaranteed to stay in bounds.
              self.setRect(rect)
      
      
      class MainWindow(QMainWindow):
          def __init__(self):
              super().__init__()
              central = QWidget(self)
              self.setCentralWidget(central)
      
              self.rect = ResizableRect()
              scene = QGraphicsScene(0, 0, 300, 300)
              scene.addItem(self.rect)
              self.view = QGraphicsView(central)
              self.view.setScene(scene)
      
              layout = QVBoxLayout(central)
              self.setLayout(layout)
              layout.addWidget(self.view)
      
              self.old_size: typing.Optional[QSize] = None
      
          def show(self):
              super().show()
              self.resize_scene()
      
          def resizeEvent(self, event: QResizeEvent):
              super().resizeEvent(event)
              self.resize_scene()
      
          def resize_scene(self):
              if not self.isVisible():
                  # Viewport size isn't set yet, so calculation won't work.
                  return
              size = self.view.maximumViewportSize()
              if self.old_size is None:
                  new_rect = QRectF(size.width()/4, size.height()/4,
                                    size.width()/2, size.height()/2)
              else:
                  old_rect = QRectF(self.rect.rect())
                  x_scale = size.width() / self.old_size.width()
                  y_scale = size.height() / self.old_size.height()
                  new_rect = QRectF(old_rect.left()*x_scale, old_rect.top()*y_scale,
                                    old_rect.width()*x_scale, old_rect.height()*y_scale)
              self.rect.setRect(new_rect)
              self.view.scene().setSceneRect(0, 0, size.width(), size.height())
              self.old_size = size
      
      
      def main():
          app = QApplication()
          window = MainWindow()
          window.show()
      
          app.exec_()
      
      
      main()
      

      【讨论】:

        【解决方案4】:

        这是我的,代码更少:

        class BoxItem(QGraphicsObject):
            def __init__(self):
                super().__init__()
                self.mousePressPos = None
                self.mousePressRect = None
                self.setAcceptHoverEvents(True)
                self.setFlag(QGraphicsItem.ItemIsMovable, True)
                self.setFlag(QGraphicsItem.ItemIsSelectable, True)
                # self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
                # self.setFlag(QGraphicsItem.ItemIsFocusable, True)
        
                self.rect = QRect(0, 0, 100, 100)
        
                self.moving = False
                self.origin = QPoint()
        
                # # Resizer actions
                # self.resizer.setPos(self.boundingRect().bottomRight() - self.r_offset)
                # self.resizer.resizeSignal.connect(self.resize)
        
            def corner_rect(self) -> QRect:
                """ Return corner rect geometry """
                return QRect(self.rect.right() - 10, self.rect.bottom() - 10, 10, 10)
        
            def boundingRect(self) -> QRectF:
                """ Override boundingRect """
                return self.rect.adjusted(-10, -10, 10, 10)
        
            def paint(self, painter, option, widget=None):
                """ OVerride paint  """
        
                brush = QBrush(QColor(255, 100, 100, 200))
                brush.setStyle(Qt.Dense7Pattern)
                painter.setBrush(brush)
                painter.drawRect(self.rect)
        
                if self.isSelected():
                    painter.setBrush(QBrush(QColor(Qt.red)))
                    painter.setPen(Qt.NoPen)
                    painter.drawRect(self.corner_rect())
        
                    # Draw selection
                    pen = QPen(QColor(Qt.green))
                    pen.setStyle(Qt.DotLine)
                    painter.setPen(pen)
                    painter.setBrush(Qt.NoBrush)
                    painter.drawRect(self.rect)
        
                self.update()
        
            def hoverMoveEvent(self, event: QMouseEvent):
                """ Override hover move Event : Display cursor """
        
                if self.isSelected() & self.corner_rect().contains(event.pos().toPoint()):
                    self.setCursor(Qt.SizeFDiagCursor)
                else:
                    self.setCursor(Qt.ArrowCursor)
        
                super().hoverMoveEvent(event)
        
            def mousePressEvent(self, event: QMouseEvent):
                """ override mouse Press Event """
                if self.isSelected() & self.corner_rect().contains(
                    QPoint(event.pos().toPoint())
                ):
                    self.moving = True
                    self.origin = self.rect.topLeft()
                else:
                    super().mousePressEvent(event)
        
            def mouseReleaseEvent(self, event: QMouseEvent):
                """ Override mouse release event """
                self.moving = False
                super().mouseReleaseEvent(event)
        
            def mouseMoveEvent(self, event: QMouseEvent):
                """ Override mouse move event """
                if self.moving:
                    # If moving is set from mousePressEvent , change geometry
                    self.prepareGeometryChange()
        
                    pos = event.pos().toPoint()
        
                    if pos.x() >= self.origin.x():
                        self.rect.setRight(pos.x())
                    else:
                        self.rect.setLeft(pos.x())
        
                    if pos.y() >= self.origin.y():
                        self.rect.setBottom(pos.y())
                    else:
                        self.rect.setTop(pos.y())
                    self.rect = self.rect.normalized()
                    self.update()
                    return
                else:
                    super().mouseMoveEvent(event)
        

        【讨论】:

          【解决方案5】:

          我也在尝试使用 QGraphicsPixmapItem 类,从@pbreach 修改调整器类,这对我有用:

          class Resizer(QGraphicsObject):
          resizeSignal = pyqtSignal(QGraphicsItem.GraphicsItemChange,QPointF)
          def __init__(self,rect = QRectF(0,0,10,10),parent=None):
              super().__init__(parent)
              self.setFlag(QGraphicsItem.ItemIsMovable,True)
              self.setFlag(QGraphicsItem.ItemIsSelectable,True)
              self.setFlag(QGraphicsItem.ItemSendsGeometryChanges,True)
              self.setCursor(Qt.SizeFDiagCursor)
              self.rect = rect
              self.hide()
          
          def boundingRect(self):
              return self.rect
          
          def paint(self,painter,option,widget=None):
              if self.isSelected():
                  pen = QPen()
                  pen.setStyle(Qt.DotLine)
                  painter.setPen(pen)
                  painter.setRenderHint(QPainter.Antialiasing)
              painter.drawEllipse(self.rect)
              self.update()
          
          def itemChange(self,change,value):
              self.prepareGeometryChange()
              if change == QGraphicsItem.ItemPositionChange:
                  if self.isSelected():
                      self.resizeSignal.emit(change,self.pos())
              return super(Resizer,self).itemChange(change,value)
          
          '''END CLASS'''
          
          class GraphicLayer(QGraphicsPixmapItem):
          def __init__(self,top_left_x,top_left_y,graphic,rect=QRectF(0,0,100,100),parent=None,scene=None):
              super().__init__(parent=parent)
              self.rect = rect
              self.setPixmap(graphic)
              self.graphic = graphic
              self.mousePressPos = None
              self.mousePressRect = None
              self.setAcceptHoverEvents(True)
              self.setFlag(QGraphicsItem.ItemIsMovable,True)
              self.setFlag(QGraphicsItem.ItemIsSelectable,True)
              self.setFlag(QGraphicsItem.ItemSendsGeometryChanges,True)
              self.setFlag(QGraphicsItem.ItemIsFocusable,True)
              self.setPos(top_left_x,top_left_y)
          
              # Resizer actions
              self.resizer = Resizer(parent=self)
              r_width = self.resizer.boundingRect().width() - 2
              self.r_offset = QPointF(r_width,r_width)
              self.resizer.setPos(self.boundingRect().bottomRight()-self.r_offset)
              self.resizer.resizeSignal.connect(self.resize)
          
          def set_tag(self,item_id):
              self.tag = item_id
          
          def get_tag(self):
              return self.tag
          
          def hoverMoveEvent(self,event):
              if self.isSelected():
                  self.resizer.show()
              else:
                  self.resizer.hide()
          
          def hoverLeave(self,event):
              self.resizer.hide()
          
          @pyqtSlot()
          def resize(self,change,value):
              pixmap = self.graphic.scaled(value.x(),value.y(),transformMode=Qt.SmoothTransformation)
              self.setPixmap(pixmap)
              self.prepareGeometryChange()
              self.update()
          
          """END OF CLASS"""
          

          这是这个类工作的一个小 gif。重要的!这是在 PyQt5 中完成的。

          请告诉我你的想法!

          【讨论】:

            猜你喜欢
            • 2020-06-02
            • 1970-01-01
            • 2014-08-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-04
            相关资源
            最近更新 更多