如何正确实现 QGraphicsItem 的对齐网格逻辑?我的不行

问题描述 投票:0回答:1

大家好,我正在开发一个项目,该项目要求我创建一个自定义 QGraphicsItemGroup,当检查小部件时该项目会捕捉到网格。捕捉到网格逻辑(部分)工作,因为当我移动项目时,它每次移动移动 10 个像素(捕捉)。然而,它从场景中的 0, 0 移动,这意味着如果该组是在 100, 100 创建的,它将像在 0, 0 创建的位置一样移动。我不知道我是否真的很好地解释了这个问题,所以随意自己玩一下吧。

class CustomGraphicsItemGroup(QGraphicsItemGroup):
    def __init__(self, widget):
        super().__init__()

        self.widgets = widget

    def paint(self, painter, option, widget=None):
        # Call the parent class paint method first
        super().paint(painter, option, widget)

        # If the item is selected, draw a custom selection highlight
        if option.state & QStyle.State_Selected:
            pen = painter.pen()
            pen.setColor(QColor('#e00202'))
            pen.setWidth(2)
            pen.setCapStyle(Qt.RoundCap)
            painter.setPen(pen)
            painter.drawRect(self.boundingRect())

    def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
        if self.widgets.isChecked():
            block_size = 10

            # Calculate the position relative to the scene's coordinate system
            scene_pos = event.scenePos()
            x = int(scene_pos.x() / block_size) * block_size
            y = int(scene_pos.y() / block_size) * block_size

            # Set the position relative to the scene's coordinate system
            self.setPos(x, y)
            
        else:
            # Call the superclass's mouseMoveEvent to move the item as normal
            super().mouseMoveEvent(event)

我尝试使用不同的数字、除法、乘法,但没有任何效果。任何帮助或代码片段表示赞赏。

python python-3.x pyqt pyqt5 qgraphicsscene
1个回答
0
投票

所以首先,在继承

QGraphicsItemGroup
时,应该考虑它的概念。该组不希望在构造函数中拥有子级。相反,项目会添加到组中。该组本身就是所有添加项目的代理。 有两种方法可以在场景中创建组。可以在场景中创建自定义组的选项如下。

  1. 创建一个组并将其添加到场景中。
group = CustomGraphicsItemGroup()
group.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True)
group.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
scene.addItem(group)
  1. 将项目分配给组。
group.addToGroup(red_item)
group.addToGroup(blue_item)

您应该始终使用 Qt 可用的工具,而不是重新发明轮子。设置正确的标志非常重要,以便项目(或组)可以选择和移动。然后使用该项目本身的

self.isSelected

对于您的问题,必须以某种方式应用鼠标的偏移量,以便不会发生突然的跳跃。这可以存储在

mousePressEvent
中。

import sys

from PySide6.QtCore import QRect, QPoint
from PySide6.QtGui import QColor, Qt
from PySide6.QtWidgets import (
    QGraphicsItemGroup,
    QStyle,
    QGraphicsItem,
    QGraphicsScene,
    QGraphicsView,
    QApplication,
    QGraphicsRectItem,
)


class CustomGraphicsItemGroup(QGraphicsItemGroup):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.mouse_offset = QPoint(0, 0)
        self.block_size = 10

    def paint(self, painter, option, widget=None):
        # Call the parent class paint method first
        super().paint(painter, option, widget)

        # If the item is selected, draw a custom selection highlight
        if option.state & QStyle.State_Selected:
            pen = painter.pen()
            pen.setColor(QColor("#e00202"))
            pen.setWidth(2)
            pen.setCapStyle(Qt.RoundCap)
            painter.setPen(pen)
            painter.drawRect(self.boundingRect())

    def mousePressEvent(self, event):
        if event.button() == Qt.MouseButton.LeftButton:
            self.mouse_offset = event.pos()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.isSelected():
            # Calculate the position relative to the scene's coordinate system
            scene_pos = event.scenePos()
            x = (
                int(scene_pos.x() / self.block_size) * self.block_size
                - self.mouse_offset.x()
            )
            y = (
                int(scene_pos.y() / self.block_size) * self.block_size
                - self.mouse_offset.y()
            )

            # Set the position relative to the scene's coordinate system
            self.setPos(x, y)
        else:
            # Call the superclass's mouseMoveEvent to move the item as normal
            super().mouseMoveEvent(event)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    scene = QGraphicsScene()
    view = QGraphicsView(scene)
    scene.setSceneRect(QRect(0, 0, 500, 500))
    view.setFixedWidth(500)
    view.setFixedHeight(500)
    view.show()

    group = CustomGraphicsItemGroup()
    group.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True)
    group.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
    scene.addItem(group)
    red_item = QGraphicsRectItem()
    red_item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True)
    red_item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
    red_item.setBrush(QColor("red"))
    red_item.setRect(0, 0, 80, 80)
    red_item.setPos(150, 150)
    group.addToGroup(red_item)

    blue_item = QGraphicsRectItem()
    blue_item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True)
    blue_item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
    blue_item.setBrush(QColor("blue"))
    blue_item.setRect(0, 0, 100, 100)
    blue_item.setPos(100, 100)
    group.addToGroup(blue_item)

    scene.addItem(blue_item)
    scene.addItem(red_item)
    sys.exit(app.exec())

© www.soinside.com 2019 - 2024. All rights reserved.