没有正确旋转图像
Not Rotating Image Correctly
我正在尝试旋转 QGraphicsView 对象的背景,但遇到了麻烦。红笔描述了我遇到的问题。
我想要的:
- 我想让箭头在屏幕中间居中。
- 我想要旋转背景图片,以我的屏幕中心为参考
- 我想在我的 QGraphicsView 中定义一个矩形。这将被定义为将显示内容划定界限的区域。因此,每次我旋转屏幕时。图像“未覆盖”的区域将始终位于矩形边界之外。
- 我想定义旋转的参考点,在我的屏幕中间 (x=VIEW_WIDTH/2, y=VIEW_HEIGHT/2)
这是我的代码:
首先,我将显示箭头 class:
from PyQt5 import QtCore, QtGui, QtWidgets # importation of some libraries
# Construnction of an arrow item, it'll be used in the QGraphicsView
class ArrowItem(QtWidgets.QGraphicsPathItem): # it inherit QgraphicsPathItem, which allows to handle it
# in the QgraphicsView
def __init__(self, parent=None): # The init method
super().__init__(parent)
self._length = -1
self._angle = 0
self._points = QtCore.QPointF(), QtCore.QPointF(), QtCore.QPointF() # with three points we
# construct a triangle.
self.length = 40.0 # the basic triangle length
self.rotate(180) # the triangle was built upside down, though I've just ran the function 'rotate'
@property
def angle(self):
"""
angle of the arrow
:return:
"""
return self._angle
@angle.setter
def angle(self, angle):
self._angle = angle
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def rotate(self, value):
"""
:param value:
"""
self._angle += value
transform = QtGui.QTransform()
transform.translate(20, 100)
transform.rotate(self._angle)
self.setTransform(transform)
# Just a function to translate the arrow, it'll not be used now!
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
下面是主要的 window 代码:
# Just setting up the main Window
class WorkScreen(QtWidgets.QMainWindow):
# Some constant variable to keep things easy to change in the future
VIEW_HEIGHT = 600
VIEW_WIDTH = 900
FLAT_BUTTON = True
"""
Attempt to paint the work screen.
"""
def __init__(self, **kwargs):
# initializing the parent class, using a 2.7 pythonic style
super(WorkScreen, self).__init__(**kwargs)
# customizing the main window.
self.setStyleSheet("""
QMainWindow{
background: rgb(180, 180, 180)}
QPushButton{
background-color: rgb(0, 200, 0);
}
""")
# the attribute 'rotation' must be zero.
self.rotation = 0
# defining some attributes
self.pixmap = QtGui.QPixmap()
self.scene = QtWidgets.QGraphicsScene()
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.pushButton_status = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_settings = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_analyse = QtWidgets.QPushButton(self.centralwidget)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.view = QtWidgets.QGraphicsView(self.centralwidget)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.pushButton_field = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_guide = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_mapping = QtWidgets.QPushButton(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.arrowItem = ArrowItem()
self.set_up()
self.view.setScene(self.scene)
self.view.scale(-1, 1)
self.image = QtGui.QImage("ola.png")
self.image = self.image.scaled(self.VIEW_WIDTH+300, self.VIEW_HEIGHT+300)
self.pixmap.convertFromImage(self.image)
self.scene.addPixmap(self.pixmap)
self.add_arrow()
def set_up(self):
"""
build the main window.
"""
self.pushButton_guide.setFlat(self.FLAT_BUTTON)
self.pushButton_mapping.setFlat(self.FLAT_BUTTON)
self.pushButton_field.setFlat(self.FLAT_BUTTON)
self.pushButton_status.setFlat(self.FLAT_BUTTON)
self.pushButton_settings.setFlat(self.FLAT_BUTTON)
self.pushButton_analyse.setFlat(self.FLAT_BUTTON)
self.setObjectName("MainWindow")
self.setMaximumWidth(1024)
self.setMaximumHeight(600)
self.resize(1024, 600)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout_3.setContentsMargins(-1, -1, 0, -1)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.pushButton_status.setObjectName("pushButton_status")
self.verticalLayout_3.addWidget(self.pushButton_status)
self.pushButton_settings.setObjectName("pushButton_settings")
self.verticalLayout_3.addWidget(self.pushButton_settings)
self.pushButton_analyse.setObjectName("pushButton_analyse")
self.verticalLayout_3.addWidget(self.pushButton_analyse)
self.horizontalLayout.addLayout(self.verticalLayout_3)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.view.setRenderHints(QtGui.QPainter.HighQualityAntialiasing | QtGui.QPainter.TextAntialiasing)
self.view.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
self.view.scale(-1, 1)
self.view.setFixedHeight(self.VIEW_HEIGHT)
self.view.setFixedWidth(self.VIEW_WIDTH)
self.view.setObjectName("view")
# self.view.setFixedWidth(self.VIEW_WIDTH)
# self.view.setFixedHeight(self.VIEW_HEIGHT)
self.verticalLayout_2.addWidget(self.view)
self.horizontalLayout.addLayout(self.verticalLayout_2)
self.verticalLayout.setContentsMargins(-1, -1, 0, -1)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_field.setObjectName("pushButton_field")
self.verticalLayout.addWidget(self.pushButton_field)
self.pushButton_guide.setObjectName("pushButton_guide")
self.verticalLayout.addWidget(self.pushButton_guide)
self.pushButton_mapping.setObjectName("pushButton_mapping")
self.verticalLayout.addWidget(self.pushButton_mapping)
self.horizontalLayout.addLayout(self.verticalLayout)
self.setCentralWidget(self.centralwidget)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
self.setMenuBar(self.menubar)
self.statusbar.setObjectName("statusbar")
self.setStatusBar(self.statusbar)
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
# Just to test
self.pushButton_status.clicked.connect(self.rotate_arrow)
self.pushButton_guide.clicked.connect(self.rotate_pixmap)
# Created just to emit a signal
def rotate_arrow(self):
"""
It'll not be used after.
"""
self.arrowItem.rotate(value=30)
def rotate_pixmap(self):
pixmap = self.pixmap
self.rotation += 15
transform = QtGui.QTransform().rotate(self.rotation, axis=QtCore.Qt.ZAxis)
pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)
self.scene.addPixmap(pixmap)
self.arrowItem.setPos(self.arrowItem.pos())
self.arrowItem.rotate(self.rotation)
self.arrowItem.setZValue(self.arrowItem.zValue()+1)
def add_arrow(self):
"""
:cvar
"""
self.scene.addItem(self.arrowItem)
self.arrowItem.setPos(QtCore.QPointF(self.VIEW_WIDTH / 2 - 50, self.VIEW_HEIGHT / 2 - 100))
def retranslateUi(self):
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_status.setText(_translate("MainWindow", "Situação"))
self.pushButton_settings.setText(_translate("MainWindow", "Configurações"))
self.pushButton_analyse.setText(_translate("MainWindow", "Analisar"))
self.pushButton_field.setText(_translate("MainWindow", "Campo"))
self.pushButton_guide.setText(_translate("MainWindow", "Guia"))
self.pushButton_mapping.setText(_translate("MainWindow", "Mapeamento"))
# calling the application
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = WorkScreen()
ui.show()
sys.exit(app.exec_())
这是我用来在背景上显示的图像:
如果你想旋转一个QGraphicsItem,没有必要使用QTransform,只需要使用setRotation 方法。另一方面,必须对图像进行缩放,使可见区域与旋转后的区域相交的区域与可见区域相同,最小区域的计算方式为:sqrt(2) x max(width, height)
。综合以上,解决办法是:
from PyQt5 import QtCore, QtGui, QtWidgets
class ArrowItem(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None):
super().__init__(parent)
self._length = -1
self._points = (
QtCore.QPointF(),
QtCore.QPointF(),
QtCore.QPointF(),
)
self.length = 40.0
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
class MainWindow(QtWidgets.QMainWindow):
VIEW_HEIGHT = 600
VIEW_WIDTH = 900
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.status_btn = QtWidgets.QPushButton("Status")
self.settings_btn = QtWidgets.QPushButton("Settings")
self.analyze_btn = QtWidgets.QPushButton("Analyze")
self.field_btn = QtWidgets.QPushButton("Field")
self.guide_btn = QtWidgets.QPushButton("Guide")
self.mapping_btn = QtWidgets.QPushButton("Mapping")
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
vlayl = QtWidgets.QVBoxLayout()
vlayl.addWidget(self.status_btn)
vlayl.addWidget(self.settings_btn)
vlayl.addWidget(self.analyze_btn)
vlayr = QtWidgets.QVBoxLayout()
vlayr.addWidget(self.field_btn)
vlayr.addWidget(self.guide_btn)
vlayr.addWidget(self.mapping_btn)
hlay = QtWidgets.QHBoxLayout(central_widget)
hlay.addLayout(vlayl)
hlay.addWidget(self.view)
hlay.addLayout(vlayr)
self.status_btn.clicked.connect(self.rotate_arrow)
self.guide_btn.clicked.connect(self.rotate_pixmap)
self.view.setFixedSize(self.VIEW_WIDTH, self.VIEW_HEIGHT)
r = self.view.mapToScene(self.view.viewport().rect()).boundingRect()
self.view.setSceneRect(r)
factor = 1.5 * max(self.VIEW_WIDTH, self.VIEW_HEIGHT)
pixmap = QtGui.QPixmap("ola.png").scaled(factor, factor)
self.pixmap_item = self.scene.addPixmap(pixmap)
center = self.pixmap_item.boundingRect().center()
self.pixmap_item.setPos(-center)
self.pixmap_item.setTransformOriginPoint(center)
self.arrow_item = ArrowItem()
self.scene.addItem(self.arrow_item)
def rotate_arrow(self):
delta = 30.0
self.arrow_item.setRotation(self.arrow_item.rotation() + delta)
def rotate_pixmap(self):
delta = 15.0
self.pixmap_item.setRotation(self.pixmap_item.rotation() + delta)
self.arrow_item.setRotation(self.arrow_item.rotation() + delta)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
我正在尝试旋转 QGraphicsView 对象的背景,但遇到了麻烦。红笔描述了我遇到的问题。
我想要的:
- 我想让箭头在屏幕中间居中。
- 我想要旋转背景图片,以我的屏幕中心为参考
- 我想在我的 QGraphicsView 中定义一个矩形。这将被定义为将显示内容划定界限的区域。因此,每次我旋转屏幕时。图像“未覆盖”的区域将始终位于矩形边界之外。
- 我想定义旋转的参考点,在我的屏幕中间 (x=VIEW_WIDTH/2, y=VIEW_HEIGHT/2)
这是我的代码:
首先,我将显示箭头 class:
from PyQt5 import QtCore, QtGui, QtWidgets # importation of some libraries
# Construnction of an arrow item, it'll be used in the QGraphicsView
class ArrowItem(QtWidgets.QGraphicsPathItem): # it inherit QgraphicsPathItem, which allows to handle it
# in the QgraphicsView
def __init__(self, parent=None): # The init method
super().__init__(parent)
self._length = -1
self._angle = 0
self._points = QtCore.QPointF(), QtCore.QPointF(), QtCore.QPointF() # with three points we
# construct a triangle.
self.length = 40.0 # the basic triangle length
self.rotate(180) # the triangle was built upside down, though I've just ran the function 'rotate'
@property
def angle(self):
"""
angle of the arrow
:return:
"""
return self._angle
@angle.setter
def angle(self, angle):
self._angle = angle
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def rotate(self, value):
"""
:param value:
"""
self._angle += value
transform = QtGui.QTransform()
transform.translate(20, 100)
transform.rotate(self._angle)
self.setTransform(transform)
# Just a function to translate the arrow, it'll not be used now!
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
下面是主要的 window 代码:
# Just setting up the main Window
class WorkScreen(QtWidgets.QMainWindow):
# Some constant variable to keep things easy to change in the future
VIEW_HEIGHT = 600
VIEW_WIDTH = 900
FLAT_BUTTON = True
"""
Attempt to paint the work screen.
"""
def __init__(self, **kwargs):
# initializing the parent class, using a 2.7 pythonic style
super(WorkScreen, self).__init__(**kwargs)
# customizing the main window.
self.setStyleSheet("""
QMainWindow{
background: rgb(180, 180, 180)}
QPushButton{
background-color: rgb(0, 200, 0);
}
""")
# the attribute 'rotation' must be zero.
self.rotation = 0
# defining some attributes
self.pixmap = QtGui.QPixmap()
self.scene = QtWidgets.QGraphicsScene()
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.pushButton_status = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_settings = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_analyse = QtWidgets.QPushButton(self.centralwidget)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.view = QtWidgets.QGraphicsView(self.centralwidget)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.pushButton_field = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_guide = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_mapping = QtWidgets.QPushButton(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.arrowItem = ArrowItem()
self.set_up()
self.view.setScene(self.scene)
self.view.scale(-1, 1)
self.image = QtGui.QImage("ola.png")
self.image = self.image.scaled(self.VIEW_WIDTH+300, self.VIEW_HEIGHT+300)
self.pixmap.convertFromImage(self.image)
self.scene.addPixmap(self.pixmap)
self.add_arrow()
def set_up(self):
"""
build the main window.
"""
self.pushButton_guide.setFlat(self.FLAT_BUTTON)
self.pushButton_mapping.setFlat(self.FLAT_BUTTON)
self.pushButton_field.setFlat(self.FLAT_BUTTON)
self.pushButton_status.setFlat(self.FLAT_BUTTON)
self.pushButton_settings.setFlat(self.FLAT_BUTTON)
self.pushButton_analyse.setFlat(self.FLAT_BUTTON)
self.setObjectName("MainWindow")
self.setMaximumWidth(1024)
self.setMaximumHeight(600)
self.resize(1024, 600)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout_3.setContentsMargins(-1, -1, 0, -1)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.pushButton_status.setObjectName("pushButton_status")
self.verticalLayout_3.addWidget(self.pushButton_status)
self.pushButton_settings.setObjectName("pushButton_settings")
self.verticalLayout_3.addWidget(self.pushButton_settings)
self.pushButton_analyse.setObjectName("pushButton_analyse")
self.verticalLayout_3.addWidget(self.pushButton_analyse)
self.horizontalLayout.addLayout(self.verticalLayout_3)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.view.setRenderHints(QtGui.QPainter.HighQualityAntialiasing | QtGui.QPainter.TextAntialiasing)
self.view.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
self.view.scale(-1, 1)
self.view.setFixedHeight(self.VIEW_HEIGHT)
self.view.setFixedWidth(self.VIEW_WIDTH)
self.view.setObjectName("view")
# self.view.setFixedWidth(self.VIEW_WIDTH)
# self.view.setFixedHeight(self.VIEW_HEIGHT)
self.verticalLayout_2.addWidget(self.view)
self.horizontalLayout.addLayout(self.verticalLayout_2)
self.verticalLayout.setContentsMargins(-1, -1, 0, -1)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_field.setObjectName("pushButton_field")
self.verticalLayout.addWidget(self.pushButton_field)
self.pushButton_guide.setObjectName("pushButton_guide")
self.verticalLayout.addWidget(self.pushButton_guide)
self.pushButton_mapping.setObjectName("pushButton_mapping")
self.verticalLayout.addWidget(self.pushButton_mapping)
self.horizontalLayout.addLayout(self.verticalLayout)
self.setCentralWidget(self.centralwidget)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
self.setMenuBar(self.menubar)
self.statusbar.setObjectName("statusbar")
self.setStatusBar(self.statusbar)
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
# Just to test
self.pushButton_status.clicked.connect(self.rotate_arrow)
self.pushButton_guide.clicked.connect(self.rotate_pixmap)
# Created just to emit a signal
def rotate_arrow(self):
"""
It'll not be used after.
"""
self.arrowItem.rotate(value=30)
def rotate_pixmap(self):
pixmap = self.pixmap
self.rotation += 15
transform = QtGui.QTransform().rotate(self.rotation, axis=QtCore.Qt.ZAxis)
pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)
self.scene.addPixmap(pixmap)
self.arrowItem.setPos(self.arrowItem.pos())
self.arrowItem.rotate(self.rotation)
self.arrowItem.setZValue(self.arrowItem.zValue()+1)
def add_arrow(self):
"""
:cvar
"""
self.scene.addItem(self.arrowItem)
self.arrowItem.setPos(QtCore.QPointF(self.VIEW_WIDTH / 2 - 50, self.VIEW_HEIGHT / 2 - 100))
def retranslateUi(self):
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_status.setText(_translate("MainWindow", "Situação"))
self.pushButton_settings.setText(_translate("MainWindow", "Configurações"))
self.pushButton_analyse.setText(_translate("MainWindow", "Analisar"))
self.pushButton_field.setText(_translate("MainWindow", "Campo"))
self.pushButton_guide.setText(_translate("MainWindow", "Guia"))
self.pushButton_mapping.setText(_translate("MainWindow", "Mapeamento"))
# calling the application
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = WorkScreen()
ui.show()
sys.exit(app.exec_())
这是我用来在背景上显示的图像:
如果你想旋转一个QGraphicsItem,没有必要使用QTransform,只需要使用setRotation 方法。另一方面,必须对图像进行缩放,使可见区域与旋转后的区域相交的区域与可见区域相同,最小区域的计算方式为:sqrt(2) x max(width, height)
。综合以上,解决办法是:
from PyQt5 import QtCore, QtGui, QtWidgets
class ArrowItem(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None):
super().__init__(parent)
self._length = -1
self._points = (
QtCore.QPointF(),
QtCore.QPointF(),
QtCore.QPointF(),
)
self.length = 40.0
@property
def length(self):
return self._length
@length.setter
def length(self, l):
self._length = l
pos_top = QtCore.QPointF(0, l * 4 / 5)
pos_left = QtCore.QPointF(-l * 3 / 5, -l / 5)
pos_right = QtCore.QPointF(
l * 3 / 5,
-l / 5,
)
path = QtGui.QPainterPath()
path.moveTo(pos_top)
path.lineTo(pos_right)
path.lineTo(pos_left)
self.setPath(path)
self._points = pos_top, pos_left, pos_right
def paint(self, painter, option, widget):
pos_top, pos_left, pos_right = self._points
left_color = QtGui.QColor("#cc0000")
right_color = QtGui.QColor("#ff0000")
bottom_color = QtGui.QColor("#661900")
path_left = QtGui.QPainterPath()
path_left.lineTo(pos_top)
path_left.lineTo(pos_left)
path_right = QtGui.QPainterPath()
path_right.lineTo(pos_top)
path_right.lineTo(pos_right)
path_bottom = QtGui.QPainterPath()
path_bottom.lineTo(pos_left)
path_bottom.lineTo(pos_right)
painter.setPen(QtGui.QColor("black"))
painter.setBrush(left_color)
painter.drawPath(path_left)
painter.setBrush(right_color)
painter.drawPath(path_right)
painter.setBrush(bottom_color)
painter.drawPath(path_bottom)
def moveTo(self, next_position, duration=100):
self._animation = QtCore.QVariantAnimation()
self._animation.setStartValue(self.pos())
self._animation.setEndValue(next_position)
self._animation.setDuration(duration)
self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
self._animation.valueChanged.connect(self.setPos)
class MainWindow(QtWidgets.QMainWindow):
VIEW_HEIGHT = 600
VIEW_WIDTH = 900
def __init__(self, parent=None):
super().__init__(parent)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.status_btn = QtWidgets.QPushButton("Status")
self.settings_btn = QtWidgets.QPushButton("Settings")
self.analyze_btn = QtWidgets.QPushButton("Analyze")
self.field_btn = QtWidgets.QPushButton("Field")
self.guide_btn = QtWidgets.QPushButton("Guide")
self.mapping_btn = QtWidgets.QPushButton("Mapping")
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
vlayl = QtWidgets.QVBoxLayout()
vlayl.addWidget(self.status_btn)
vlayl.addWidget(self.settings_btn)
vlayl.addWidget(self.analyze_btn)
vlayr = QtWidgets.QVBoxLayout()
vlayr.addWidget(self.field_btn)
vlayr.addWidget(self.guide_btn)
vlayr.addWidget(self.mapping_btn)
hlay = QtWidgets.QHBoxLayout(central_widget)
hlay.addLayout(vlayl)
hlay.addWidget(self.view)
hlay.addLayout(vlayr)
self.status_btn.clicked.connect(self.rotate_arrow)
self.guide_btn.clicked.connect(self.rotate_pixmap)
self.view.setFixedSize(self.VIEW_WIDTH, self.VIEW_HEIGHT)
r = self.view.mapToScene(self.view.viewport().rect()).boundingRect()
self.view.setSceneRect(r)
factor = 1.5 * max(self.VIEW_WIDTH, self.VIEW_HEIGHT)
pixmap = QtGui.QPixmap("ola.png").scaled(factor, factor)
self.pixmap_item = self.scene.addPixmap(pixmap)
center = self.pixmap_item.boundingRect().center()
self.pixmap_item.setPos(-center)
self.pixmap_item.setTransformOriginPoint(center)
self.arrow_item = ArrowItem()
self.scene.addItem(self.arrow_item)
def rotate_arrow(self):
delta = 30.0
self.arrow_item.setRotation(self.arrow_item.rotation() + delta)
def rotate_pixmap(self):
delta = 15.0
self.pixmap_item.setRotation(self.pixmap_item.rotation() + delta)
self.arrow_item.setRotation(self.arrow_item.rotation() + delta)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())