QGraphicsItem::itemChange 通知位置更改,但不通知大小更改

Joe*_*Joe 5 qt

我有一个从 QGraphicsEllipseItem 派生的类,其中我需要知道它的位置或大小何时以任何方式发生变化。我用鼠标处理大小调整并调用 QGraphicsEllipse::setRect。

好的,所以我尽职尽责地覆盖了类中的 itemChange() 方法,然后在创建它后小心地设置了 ItemSendsGeometryChanges 标志

// Returns a human readable string for any GraphicsItemChange enum value

inline std::string EnumName(QGraphicsItem::GraphicsItemChange e);

// Simple test ellipse class

class MyEllipse : public QGraphicsEllipseItem
{
public:
    MyEllipse(int x, int y, int w, int h) : QGraphicsEllipseItem(x, y, w, h)
    {
        setFlags(
            QGraphicsItem::ItemIsSelectable 
            | QGraphicsItem::ItemIsMovable 
            | QGraphicsItem::ItemSendsGeometryChanges);
    }


    // QGraphicItem overrides
    virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override
    {
        std::stringstream oss;
        oss << "ItemChange " << EnumName(change) << std::endl;
        OutputDebugString(oss.str().c_str());
        return __super::itemChange(change, value);
    }
};
Run Code Online (Sandbox Code Playgroud)

我的主代码创建其中之一,将其添加到场景中,然后尝试移动/调整其大小。

虽然我在椭圆上调用 setPos() 后总是收到通知,但在调用 setRect() 后我没有收到任何通知。我可以使用 setRect 完全更改椭圆的几何形状,但我的 itemChange 覆盖从未被调用。没有任何标志。

现在显然改变项目的矩形正在改变它的几何形状,那么我错过了什么?

我还应该设置其他标志吗?我应该使用其他一些方法来改变椭圆的大小?我可以覆盖其他一些虚拟通知吗?

ilo*_*XXI 3

问题是的位置与的矩形QGraphicsItem无关。QGraphicsEllipseItem第一个是项目相对于其父项目的位置,或者如果是的话NULL,相对于其场景的位置。最后一个是相对于应绘制椭圆的项目位置的矩形。场景和QGraphicsItem核心不知道有任何变化。

我们来看看这个测试:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&scene);
    QGraphicsEllipseItem item(10, 20, 30, 40);
    scene.addItem(&item);

    qDebug() << item.pos() << item.scenePos() << item.boundingRect();
    item.setRect(110, 120, 30, 40);
    qDebug() << item.pos() << item.scenePos() << item.boundingRect();

    view.resize(500, 500);
    view.show();

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

输出是:

QPointF(0,0) QPointF(0,0) QRectF(9.5,19.5 31x41)
QPointF(0,0) QPointF(0,0) QRectF(109.5,119.5 31x41)
Run Code Online (Sandbox Code Playgroud)

可能的出路:

  1. 使用setTransform。变换矩阵的变化被standards跟踪QGraphicsitem,并且itemChange会收到相应的变化。但我猜想非恒等矩阵会降低性能(未检查)。
  2. 实现您自己的功能,例如setRect您将手动跟踪几何形状更改。
  3. 子类QGraphicsItem,不是QGraphicsEllipseItem。在这种情况下,您可以防止无法跟踪的几何图形更改,因为它们是通过您的规则执行的。它看起来像这样:

    class EllipseItem: public QGraphicsItem
    {
    public:
        // Here are constructors and a lot of standard things for
        // QGraphicsItem subclassing, see Qt Assistant.
        ...
    
        // This method is not related with QGraphicsEllipseItem at all.
        void setRect(const QRectF &newRect)
        {
            setPos(newRect.topLeft());
            _width = newRect.width();
            _height = newRect.height();
            update();
        }
    
        QRectF boundingRect() const override
        {
            return bRect();
        }
    
        void paint(QPainter * painter, const QStyleOptionGraphicsItem * option,
                   QWidget * widget = nullptr) override
        {
            painter->drawRect(bRect());
        }
    
    private:
        qreal   _width;
        qreal   _height;
    
        QRectF bRect() const
        {
            return QRectF(0, 0, _width, _height);
        }
    };
    
    Run Code Online (Sandbox Code Playgroud)

    您还应该跟踪项目转换和移动QGraphicsItem::itemChange