【发布时间】:2021-11-17 17:17:29
【问题描述】:
相对于场景中的 QGraphicsPixmapItem 检索 QGraphicsRectItem 坐标的最佳方法是什么?
这是我的主窗口类的代码。
import sys
from PySide2 import QtCore, QtGui
from PySide2.QtWidgets import *
from PySide2.QtGui import QBrush, QPen
class main_window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 500, 500)
self.rect = ResizableRect(100, 100, 100, 100)
self.rect.setZValue(1)
self.rect.setRotation(10)
self.view = QGraphicsView(self)
self.scene = QGraphicsScene(self.view)
self.scene.addItem(self.rect)
pixmap = QtGui.QPixmap("images/sadcat.jpg")
pixmap_item = self.scene.addPixmap(pixmap)
pixmap_item.setPixmap(pixmap)
self.view.setSceneRect(0, 0, 500,500)
self.view.setScene(self.scene)
self.slider = QSlider(QtCore.Qt.Horizontal)
self.slider.setMinimum(0)
self.slider.setMaximum(90)
vbox = QVBoxLayout(self)
vbox.addWidget(self.view)
vbox.addWidget(self.slider)
self.setLayout(vbox)
self.slider.valueChanged.connect(self.rotate)
def rotate(self, value):
self.angle = int(value)
self.rect.setRotation(self.angle)
这是自定义 QGraphicsRectItem 的代码(感谢 Resize a QGraphicsItem with the mouse)
class ResizableRect(QGraphicsRectItem):
def __init__(self, *args):
super().__init__(*args)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, True)
self.setPen(QPen(QBrush(QtGui.QColor('red')), 5))
self.selected_edge = None
self.first_pos = self.click_rect = None
def mousePressEvent(self, event):
""" The mouse is pressed, start tracking movement. """
self.first_pos = event.pos()
self.rect_shape = self.rect()
if abs(self.rect_shape.left() - self.first_pos.x()) < 5:
self.selected_edge = 'left'
elif abs(self.rect_shape.right() - self.first_pos.x()) < 5:
self.selected_edge = 'right'
elif abs(self.rect_shape.top() - self.first_pos.y()) < 5:
self.selected_edge = 'top'
elif abs(self.rect_shape.bottom() - self.first_pos.y()) < 5:
self.selected_edge = 'bottom'
else:
self.selected_edge = None
self.first_pos = event.pos()
self.click_rect = self.rect_shape
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
""" Continue tracking movement while the mouse is pressed. """
# Calculate how much the mouse has moved since the click.
self.pos = event.pos()
x_diff = self.pos.x() - self.first_pos.x()
y_diff = self.pos.y() - self.first_pos.y()
# Start with the rectangle as it was when clicked.
self.rect_shape = QtCore.QRectF(self.click_rect)
# Then adjust by the distance the mouse moved.
if self.selected_edge is None:
self.rect_shape.translate(x_diff, y_diff)
elif self.selected_edge == 'top':
self.rect_shape.adjust(0, y_diff, 0, 0)
elif self.selected_edge == 'left':
self.rect_shape.adjust(x_diff, 0, 0, 0)
elif self.selected_edge == 'bottom':
self.rect_shape.adjust(0, 0, 0, y_diff)
elif self.selected_edge == 'right':
self.rect_shape.adjust(0, 0, x_diff, 0)
self.setRect(self.rect_shape)
coor = self.rect_shape.getRect()
self.setTransformOriginPoint(coor[0] + coor[2]/2, coor[1] + coor[3]/2)
print(coor)
主窗口 GUI 如下所示。
【问题讨论】:
-
Graphics View 框架中的所有坐标都是基于浮点的。不幸的是,您没有提供minimal reproducible example,因此很难更好地理解您的问题。除此之外,如果你需要将变换的原点设置为矩形的中心,你可以使用
rect.center()。 -
嗨@musicamante!谢谢你一直对我这么有耐心。我稍后会详细说明我的问题。
-
(供将来参考,无需告诉您要编辑问题,只需在更新后添加评论,因为 cmets 应始终保持在最低限度)现在,问题有点复杂。事实是 QGraphicsRectItem 的矩形并不总是与项目的位置匹配:您可以将 QGraphicsRectItem 定位在 10x10 处,使用 rect(20, 50, 50, 100),结果是矩形将被绘制30x60。添加旋转使其更加复杂,因为矩形的原点将在项目坐标中考虑,但如果您需要 ->
-
-> 要知道矩形的实际原点,您必须将其映射到场景(考虑任何变换,包括旋转和缩放)。因此,必须了解三件事:1.您对什么坐标感兴趣?现在你总是得到 item 坐标中的矩形; 2.那个矩形的最终目的是什么(我相信它正在裁剪,但我不确定)? 3. 这些坐标是如何使用的,或者你想向用户展示什么?
-
@musicamante 这些值与场景相关,而不是视口。您想要矩形相对于哪个坐标系:图像或视口或自身项目或场景?
标签: python pyqt pyside qgraphicsscene qgraphicsitem