Pyqt5 Qgraphicsview scaled appropriately on load
我有一些 QGraphicItems 在多个预定的 X 和 Y 坐标处加载。我有一个名为
我的问题是如何让对象在加载时与用户单击按钮时的缩放比例相同。感谢您的帮助。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import sys from math import sqrt class Point(QGraphicsItem): def __init__(self, x, y): super(Point, self).__init__() self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.rectF = QRectF(0, 0, 30, 30) self.x=x self.y=y self._brush = QBrush(Qt.black) def setBrush(self, brush): self._brush = brush self.update() def boundingRect(self): return self.rectF def paint(self, painter=None, style=None, widget=None): painter.fillRect(self.rectF, self._brush) def hoverMoveEvent(self, event): point = event.pos().toPoint() print(point) QGraphicsItem.hoverMoveEvent(self, event) class Viewer(QGraphicsView): photoClicked = pyqtSignal(QPoint) rectChanged = pyqtSignal(QRect) def __init__(self, parent): super(Viewer, self).__init__(parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.setMouseTracking(True) self.origin = QPoint() self.changeRubberBand = False self._zoom = 0 self._empty = True self._scene = QGraphicsScene(self) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFrameShape(QFrame.NoFrame) self.area = float() self.setPoints() self.fitInView() def setItems(self): self.data = {'x': [-2414943.8686, -2417160.6592, -2417160.6592, -2417856.1783, -2417054.7618, -2416009.9966, -2416012.5232, -2418160.8952, -2418160.8952, -2416012.5232, -2417094.7694, -2417094.7694], 'y': [10454269.7008, 10454147.2672, 10454147.2672, 10453285.2456, 10452556.8132, 10453240.2808, 10455255.8752, 10455183.1912, 10455183.1912, 10455255.8752, 10456212.5959, 10456212.5959]} maxX = max(self.data['x']) minX = min(self.data['x']) maxY = max(self.data['y']) minY = min(self.data['y']) distance = sqrt((maxX-minX)**2+(maxY-minY)**2) self.area = QRectF(minX, minY, distance, distance) for i,x in enumerate(self.data['x']): x = self.data['x'][i] y = self.data['y'][i] p = Point(x,y) p.setPos(x,y) self._scene.addItem(p) self.setScene(self._scene) def fitInView(self, scale=True): rect = QRectF(self.area) if not rect.isNull(): self.setSceneRect(rect) unity = self.transform().mapRect(QRectF(0, 0, 1, 1)) self.scale(1 / unity.width(), 1 / unity.height()) viewrect = self.viewport().rect() scenerect = self.transform().mapRect(rect) factor = min(viewrect.width() / scenerect.width(), viewrect.height() / scenerect.height()) self.scale(factor, factor) self._zoom = 0 print('viewrect.width: '+str(viewrect.width())) print('scenerect.width: '+str(scenerect.width())) print('viewrect.height: '+str(viewrect.height())) print('scenerect.height: '+str(scenerect.height())) def setPoints(self): self._zoom = 0 self.setItems() self.setDragMode(self.ScrollHandDrag) # self.fitInView() def wheelEvent(self, event): if event.angleDelta().y() > 0: factor = 1.25 self._zoom += 1 else: factor = 0.8 self._zoom -= 1 if self._zoom > 0: self.scale(factor, factor) elif self._zoom == 0: self.fitInView() else: self._zoom = 0 def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = event.pos() self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rectChanged.emit(self.rubberBand.geometry()) self.rubberBand.show() self.changeRubberBand = True return #QGraphicsView.mousePressEvent(self,event) elif event.button() == Qt.MidButton: self.viewport().setCursor(Qt.ClosedHandCursor) self.original_event = event handmade_event = QMouseEvent(QEvent.MouseButtonPress,QPointF(event.pos()),Qt.LeftButton,event.buttons(),Qt.KeyboardModifiers()) QGraphicsView.mousePressEvent(self,handmade_event) super(Viewer, self).mousePressEvent(event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.changeRubberBand = False QGraphicsView.mouseReleaseEvent(self,event) elif event.button() == Qt.MidButton: self.viewport().setCursor(Qt.OpenHandCursor) handmade_event = QMouseEvent(QEvent.MouseButtonRelease,QPointF(event.pos()),Qt.LeftButton,event.buttons(),Qt.KeyboardModifiers()) QGraphicsView.mouseReleaseEvent(self,handmade_event) super(Viewer, self).mouseReleaseEvent(event) def mouseMoveEvent(self, event): if self.changeRubberBand: self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) self.rectChanged.emit(self.rubberBand.geometry()) QGraphicsView.mouseMoveEvent(self,event) super(Viewer, self).mouseMoveEvent(event) class Window(QWidget): def __init__(self): super(Window, self).__init__() self.viewer = Viewer(self) self.btnLoad = QToolButton(self) self.btnLoad.setText('Fit Into View') self.btnLoad.clicked.connect(self.fitPoints) VBlayout = QVBoxLayout(self) VBlayout.addWidget(self.viewer) HBlayout = QHBoxLayout() HBlayout.setAlignment(Qt.AlignLeft) HBlayout.addWidget(self.btnLoad) VBlayout.addLayout(HBlayout) self.viewer.fitInView() def fitPoints(self): self.viewer.fitInView() if __name__ == '__main__': import sys app = QApplication(sys.argv) window = Window() window.setGeometry(500, 300, 800, 600) window.show() sys.exit(app.exec_()) |
在 QGraphicsView 显示之前的瞬间,内部元素被重新计算,以便您观察到不同的行为,因此解决方案是在显示后立即应用该函数。为此,至少有 2 个选项:
1。 QTimer.singleShot(0, ...):
1 2 3 4 | # ... self.setPoints() QTimer.singleShot(0, self.fitInView) # ... |
1。覆盖 Viewer
的 showEvent 方法
1 2 3 | def showEvent(self, event): self.fitInView() super(Viewer, self).showEvent(event) |