class CustomProxy(QGraphicsProxyWidget): def __init__(self, parent=None, wFlags=0): super(CustomProxy, self).__init__(parent, wFlags) self.popupShown = False self.currentPopup = None self.timeLine = QTimeLine(250, self) self.timeLine.valueChanged.connect(self.updateStep) self.timeLine.stateChanged.connect(self.stateChanged) def boundingRect(self): return QGraphicsProxyWidget.boundingRect(self).adjusted(0, 0, 10, 10) def paintWindowFrame(self, painter, option, widget): color = QColor(0, 0, 0, 64) r = self.windowFrameRect() right = QRectF(r.right(), r.top() + 10, 10, r.height() - 10) bottom = QRectF(r.left() + 10, r.bottom(), r.width(), 10) intersectsRight = right.intersects(option.exposedRect) intersectsBottom = bottom.intersects(option.exposedRect) if intersectsRight and intersectsBottom: path = QPainterPath() path.addRect(right) path.addRect(bottom) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawPath(path) elif intersectsBottom: painter.fillRect(bottom, color) elif intersectsRight: painter.fillRect(right, color) super(CustomProxy, self).paintWindowFrame(painter, option, widget) def hoverEnterEvent(self, event): super(CustomProxy, self).hoverEnterEvent(event) self.scene().setActiveWindow(self) if self.timeLine.currentValue != 1: self.zoomIn() def hoverLeaveEvent(self, event): super(CustomProxy, self).hoverLeaveEvent(event) if not self.popupShown and ( self.timeLine.direction() != QTimeLine.Backward or self.timeLine.currentValue() != 0): self.zoomOut() def sceneEventFilter(self, watched, event): if watched.isWindow() and (event.type() == QEvent.UngrabMouse or event.type() == QEvent.GrabMouse): self.popupShown = watched.isVisible() if not self.popupShown and not self.isUnderMouse(): self.zoomOut() return super(CustomProxy, self).sceneEventFilter(watched, event) def itemChange(self, change, value): if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange: if change == self.ItemChildAddedChange: self.currentPopup = value self.currentPopup.setCacheMode(self.ItemCoordinateCache) if self.scene() is not None: self.currentPopup.installSceneEventFilter(self) elif self.scene() is not None: self.currentPopup.removeSceneEventFilter(self) self.currentPopup = None elif self.currentPopup is not None and change == self.ItemSceneHasChanged: self.currentPopup.installSceneEventFilter(self) return super(CustomProxy, self).itemChange(change, value) def updateStep(self, step): r = self.boundingRect() self.setTransform(QTransform() \ .translate(r.width() / 2, r.height() / 2)\ .rotate(step * 30, Qt.XAxis)\ .rotate(step * 10, Qt.YAxis)\ .rotate(step * 5, Qt.ZAxis)\ .scale(1 + 1.5 * step, 1 + 1.5 * step)\ .translate(-r.width() / 2, -r.height() / 2)) def stateChanged(self, state): if state == QTimeLine.Running: if self.timeLine.direction() == QTimeLine.Forward: self.setCacheMode(self.NoCache) elif state == QTimeLine.NotRunning: if self.timeLine.direction() == QTimeLine.Backward: self.setCacheMode(self.DeviceCoordinateCache) def zoomIn(self): if self.timeLine.direction() != QTimeLine.Forward: self.timeLine.setDirection(QTimeLine.Forward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start() def zoomOut(self): if self.timeLine.direction() != QTimeLine.Backward: self.timeLine.setDirection(QTimeLine.Backward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start()
class CustomProxy(QGraphicsProxyWidget): def __init__(self, parent=None, wFlags=0): super(CustomProxy, self).__init__(parent, wFlags) self.popupShown = False self.currentPopup = None self.timeLine = QTimeLine(250, self) self.timeLine.valueChanged.connect(self.updateStep) self.timeLine.stateChanged.connect(self.stateChanged) def boundingRect(self): return QGraphicsProxyWidget.boundingRect(self).adjusted(0, 0, 10, 10) def paintWindowFrame(self, painter, option, widget): color = QColor(0, 0, 0, 64) r = self.windowFrameRect() right = QRectF(r.right(), r.top()+10, 10, r.height()-10) bottom = QRectF(r.left()+10, r.bottom(), r.width(), 10) intersectsRight = right.intersects(option.exposedRect) intersectsBottom = bottom.intersects(option.exposedRect) if intersectsRight and intersectsBottom: path = QPainterPath() path.addRect(right) path.addRect(bottom) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawPath(path) elif intersectsBottom: painter.fillRect(bottom, color) elif intersectsRight: painter.fillRect(right, color) super(CustomProxy, self).paintWindowFrame(painter, option, widget) def hoverEnterEvent(self, event): super(CustomProxy, self).hoverEnterEvent(event) self.scene().setActiveWindow(self) if self.timeLine.currentValue != 1: self.zoomIn() def hoverLeaveEvent(self, event): super(CustomProxy, self).hoverLeaveEvent(event) if not self.popupShown and (self.timeLine.direction() != QTimeLine.Backward or self.timeLine.currentValue() != 0): self.zoomOut() def sceneEventFilter(self, watched, event): if watched.isWindow() and (event.type() == QEvent.UngrabMouse or event.type() == QEvent.GrabMouse): self.popupShown = watched.isVisible() if not self.popupShown and not self.isUnderMouse(): self.zoomOut() return super(CustomProxy, self).sceneEventFilter(watched, event) def itemChange(self, change, value): if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange : if change == self.ItemChildAddedChange: self.currentPopup = value self.currentPopup.setCacheMode(self.ItemCoordinateCache) if self.scene() is not None: self.currentPopup.installSceneEventFilter(self) elif self.scene() is not None: self.currentPopup.removeSceneEventFilter(self) self.currentPopup = None elif self.currentPopup is not None and change == self.ItemSceneHasChanged: self.currentPopup.installSceneEventFilter(self) return super(CustomProxy, self).itemChange(change, value) def updateStep(self, step): r = self.boundingRect() self.setTransform(QTransform() \ .translate(r.width() / 2, r.height() / 2)\ .rotate(step * 30, Qt.XAxis)\ .rotate(step * 10, Qt.YAxis)\ .rotate(step * 5, Qt.ZAxis)\ .scale(1 + 1.5 * step, 1 + 1.5 * step)\ .translate(-r.width() / 2, -r.height() / 2)) def stateChanged(self, state): if state == QTimeLine.Running: if self.timeLine.direction() == QTimeLine.Forward: self.setCacheMode(self.NoCache) elif state == QTimeLine.NotRunning: if self.timeLine.direction() == QTimeLine.Backward: self.setCacheMode(self.DeviceCoordinateCache) def zoomIn(self): if self.timeLine.direction() != QTimeLine.Forward: self.timeLine.setDirection(QTimeLine.Forward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start() def zoomOut(self): if self.timeLine.direction() != QTimeLine.Backward: self.timeLine.setDirection(QTimeLine.Backward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start()