您需要自己实现调整大小.要做到这一点,你需要继承QGraphicsRectItem
和实现鼠标事件处理函数:mousePressEvent
,mouseMoveEvent
,mouseReleaseEvent
.总体思路如下:
您可以创建一组可用于调整形状大小的手柄.
通过跟踪手柄位置更改,您可以计算形状的新几何图形.
我之前写了一些代码,它与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()