在缩放 QGraphicsItem 时设置变换点
Setting Transformation Point On Scaling QGraphicsItem
我遇到了问题。
在给定的代码中,动画和转换工作完美。但是,我想要设置转换点。
根据我的说法,我必须设置 .setTransformationOriginPoint(item.boundingRect().center()
但是,看起来转换是从左上角开始的。
我什至尝试手动设置点,但仍然没有用。
代码如下:
from typing import Any
from PyQt6.QtCore import QPointF, QSequentialAnimationGroup, Qt, pyqtSignal
from PyQt6.QtGui import QColor, QEnterEvent, QMouseEvent , QTransform
from PyQt6.QtWidgets import QApplication, QGraphicsColorizeEffect, QGraphicsScene, QGraphicsView, QMainWindow, QWidget
from functools import partial
from PyQt6.QtSvgWidgets import QGraphicsSvgItem
from typing import Any, Callable
from PyQt6.QtCore import QEasingCurve, QPoint, QPropertyAnimation, QRect, QVariantAnimation
from PyQt6.QtWidgets import QGraphicsOpacityEffect, QWidget
class Animation:
def variantAnimation(startValue: Any , endValue: Any , duration: int , callback: Callable) -> QVariantAnimation:
animation = QVariantAnimation()
animation.setStartValue(startValue)
animation.setEndValue(endValue)
animation.setDuration(duration)
animation.setEasingCurve(QEasingCurve.Type.InOutQuad)
animation.valueChanged.connect(callback)
return animation
class Rounded_Jolly_Button(QGraphicsView):
clicked = pyqtSignal()
def __init__(self , parent: QWidget , location: str):
super().__init__(parent)
self.location = location
self.setStyleSheet("background-color: #2E3440; border-radius: 22px")
self.setFixedSize(45 , 45)
self.setCursor(Qt.CursorShape.PointingHandCursor)
self._scene = QGraphicsScene()
self.setScene(self._scene)
self._scene.setSceneRect(0 , 0 , 40 , 40)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setStyles()
def setStyles(self):
color = QGraphicsColorizeEffect()
color.setColor(QColor("#D8DEE9"))
svg = QGraphicsSvgItem("./assets/google.svg")
svg.setAcceptHoverEvents(True)
svg.setPos(10 , 10)
svg.setGraphicsEffect(color)
self._scene.addItem(svg)
svg.setTransformOriginPoint(svg.boundingRect().center())
self.animations = QSequentialAnimationGroup()
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.0 , 1.0) , QPointF(1.25 , 0.75) , 270 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.25 , 0.75) , QPointF(.75 , 1.25) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(.75 , 1.25) , QPointF(1.15 , .85) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.15 , 0.85) , QPointF(.95 , 1.05) , 135 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(.95 , 1.05) , QPointF(1.05 , 0.95) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.05 , 0.95) , QPointF(1 , 1) , 225 , partial(self.updateTransform , svg)))
def enterEvent(self, event: QEnterEvent) -> None:
self.animations.start()
return super().enterEvent(event)
def mousePressEvent(self, ev: QMouseEvent) -> None:
if(ev.button() == Qt.MouseButton.LeftButton):
self.clicked.emit()
return super().mousePressEvent(ev)
def updateTransform(self , target: QGraphicsSvgItem , newValue: Any):
target.setTransform(QTransform().scale(newValue.x() , newValue.y()))
def window():
app = QApplication([])
window = QMainWindow()
parent = QWidget()
button = Rounded_Jolly_Button(parent , None)
window.setCentralWidget(parent)
window.show()
exit(app.exec())
if __name__ == '__main__':
window()
注意:./assets/google.svg
包含从 Font Awesome 下载并调整为 20x20 像素的 svg
转换总是在原点设置为 (0, 0)
的情况下创建,并且在使用 setTransform()
时,项目的 transformOriginPoint
将被忽略,因为它仅用于内部 setRotation
和 setScale
函数。
在内部,当旋转或缩放设置为 QGraphicsItem 时,将按以下方式应用转换:
- 创建一个新的转换;
- 将其平移到原点;
- 应用旋转;
- 应用比例;
- 恢复翻译回来;
由于您需要进行非对称缩放(setScale
未提供),因此您需要对新变换进行相同的缩放。
def updateTransform(self , target: QGraphicsSvgItem , newValue: Any):
origin = target.transformOriginPoint()
transform = QTransform().translate(origin.x(), origin.y())
transform.scale(newValue.x(), newValue.y())
transform.translate(-origin.x(), -origin.y())
target.setTransform(transform)
我遇到了问题。
在给定的代码中,动画和转换工作完美。但是,我想要设置转换点。
根据我的说法,我必须设置 .setTransformationOriginPoint(item.boundingRect().center()
但是,看起来转换是从左上角开始的。
我什至尝试手动设置点,但仍然没有用。
代码如下:
from typing import Any
from PyQt6.QtCore import QPointF, QSequentialAnimationGroup, Qt, pyqtSignal
from PyQt6.QtGui import QColor, QEnterEvent, QMouseEvent , QTransform
from PyQt6.QtWidgets import QApplication, QGraphicsColorizeEffect, QGraphicsScene, QGraphicsView, QMainWindow, QWidget
from functools import partial
from PyQt6.QtSvgWidgets import QGraphicsSvgItem
from typing import Any, Callable
from PyQt6.QtCore import QEasingCurve, QPoint, QPropertyAnimation, QRect, QVariantAnimation
from PyQt6.QtWidgets import QGraphicsOpacityEffect, QWidget
class Animation:
def variantAnimation(startValue: Any , endValue: Any , duration: int , callback: Callable) -> QVariantAnimation:
animation = QVariantAnimation()
animation.setStartValue(startValue)
animation.setEndValue(endValue)
animation.setDuration(duration)
animation.setEasingCurve(QEasingCurve.Type.InOutQuad)
animation.valueChanged.connect(callback)
return animation
class Rounded_Jolly_Button(QGraphicsView):
clicked = pyqtSignal()
def __init__(self , parent: QWidget , location: str):
super().__init__(parent)
self.location = location
self.setStyleSheet("background-color: #2E3440; border-radius: 22px")
self.setFixedSize(45 , 45)
self.setCursor(Qt.CursorShape.PointingHandCursor)
self._scene = QGraphicsScene()
self.setScene(self._scene)
self._scene.setSceneRect(0 , 0 , 40 , 40)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setStyles()
def setStyles(self):
color = QGraphicsColorizeEffect()
color.setColor(QColor("#D8DEE9"))
svg = QGraphicsSvgItem("./assets/google.svg")
svg.setAcceptHoverEvents(True)
svg.setPos(10 , 10)
svg.setGraphicsEffect(color)
self._scene.addItem(svg)
svg.setTransformOriginPoint(svg.boundingRect().center())
self.animations = QSequentialAnimationGroup()
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.0 , 1.0) , QPointF(1.25 , 0.75) , 270 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.25 , 0.75) , QPointF(.75 , 1.25) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(.75 , 1.25) , QPointF(1.15 , .85) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.15 , 0.85) , QPointF(.95 , 1.05) , 135 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(.95 , 1.05) , QPointF(1.05 , 0.95) , 90 , partial(self.updateTransform , svg)))
self.animations.addAnimation(Animation.variantAnimation(QPointF(1.05 , 0.95) , QPointF(1 , 1) , 225 , partial(self.updateTransform , svg)))
def enterEvent(self, event: QEnterEvent) -> None:
self.animations.start()
return super().enterEvent(event)
def mousePressEvent(self, ev: QMouseEvent) -> None:
if(ev.button() == Qt.MouseButton.LeftButton):
self.clicked.emit()
return super().mousePressEvent(ev)
def updateTransform(self , target: QGraphicsSvgItem , newValue: Any):
target.setTransform(QTransform().scale(newValue.x() , newValue.y()))
def window():
app = QApplication([])
window = QMainWindow()
parent = QWidget()
button = Rounded_Jolly_Button(parent , None)
window.setCentralWidget(parent)
window.show()
exit(app.exec())
if __name__ == '__main__':
window()
注意:./assets/google.svg
包含从 Font Awesome 下载并调整为 20x20 像素的 svg
转换总是在原点设置为 (0, 0)
的情况下创建,并且在使用 setTransform()
时,项目的 transformOriginPoint
将被忽略,因为它仅用于内部 setRotation
和 setScale
函数。
在内部,当旋转或缩放设置为 QGraphicsItem 时,将按以下方式应用转换:
- 创建一个新的转换;
- 将其平移到原点;
- 应用旋转;
- 应用比例;
- 恢复翻译回来;
由于您需要进行非对称缩放(setScale
未提供),因此您需要对新变换进行相同的缩放。
def updateTransform(self , target: QGraphicsSvgItem , newValue: Any):
origin = target.transformOriginPoint()
transform = QTransform().translate(origin.x(), origin.y())
transform.scale(newValue.x(), newValue.y())
transform.translate(-origin.x(), -origin.y())
target.setTransform(transform)