1

I want to make one QGraphicsItem in a QGraphicsScene move (or change size) when another one moves. But, trying to access either QGraphicsItem from the QGraphicsScene object causes crashes.

Here's a dummy example. I want to automatically:

  1. Resize BlueItem's width when I click and drag RedItem.

  2. Move RedItem when I click and drag BlueItem.

The dummy code:

redItem.h (A pixmap item)

#include <QGraphicsPixmapItem>

class RedItem : public QGraphicsPixmapItem
{
public:
  RedItem();

protected:
  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};

redItem.cpp

RedItem::RedItem()
{
  setPixmap(QPixmap(redPixMap));
  setFlags(ItemIsMovable);
  setCacheMode(DeviceCoordinateCache);
}

void RedItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
  setPos(event->scenePos(),0); //I can override this part just fine.
}

blueItem.h (A resizable rectangle item)

#include <QGraphicsRectItem>

class BlueItem : public QGraphicsRectItem
{
public:
  BlueItem();

protected:
  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};

blueItem.cpp is similar to redItem.cpp

graphicsViewWidget.h (The GraphicsView)

#include <QGraphicsView>
#include "blueItem.h"
#include "redItem.h"


class GraphicsViewWidget : public QGraphicsView
{
  Q_OBJECT
public:
  explicit GraphicsViewWidget(QWidget *parent = 0);

protected:
  virtual void mouseMoveEvent(QMouseEvent *event);

private:
  RedItem *red;
  BlueItem *blue;
};

graphicsViewWidget.cpp

#include "graphicsViewWidget.h"
#include <QRectF>

void Qx::createItem(int frame)
{

    red = new RedItem;
    red->setPos(0, 0);
    scene()->addItem(red);


    blue = new BlueItem;
    blue->setPos(10, 10);
    scene()->addItem(blue);
}

void GraphicsViewWidget::mouseMoveEvent(QMouseEvent *event) //QGraphicsSceneMouseEvent
{
  QGraphicsView::mouseMoveEvent(event);

  //if(redItem moves)
  //  resize blueItem;

  //if(blueItem moves)
  //  move redItem;

}

Any help or advice would be greatly appreciated.

horchler
  • 18,384
  • 4
  • 37
  • 73
Graeme Rock
  • 601
  • 5
  • 21

1 Answers1

3

If you make item B a child of item A, then it will live in its coordinate space. This means all transformations - moving, scaling, rotating... everything you apply to the parent item will also be applied to all its children and their children and so on...

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Interesting! I was under the impression items could only be created in a scene. Just to be clear, you mean you would initialize item B in the constructor of item A, right? – Graeme Rock Oct 21 '16 at 21:11
  • 1
    You can add items to the scene or to other existing items, be that on or off scene. You can use the constructor which passes a parent, or the `setParentItem()` function. If the parent is already added to the scene the new object will automatically be added to it as well. – dtech Oct 21 '16 at 21:12
  • Do you have a link to an example of this being done? – Graeme Rock Oct 21 '16 at 21:16
  • Also, regardless of whether you set the parent using the constructor or setParentItem, don't add the child to the scene; it will cause (harmless) warnings from QGraphicsScene::addItem. When you add the parent to the scene, the children are added automatically. Or, if the parent is already in the scene, children added to the parent are automatically added to the scene. – goug Oct 21 '16 at 21:17
  • @GraemeRock just `blue->setParentItem(red)` and then `scene()->addItem(red)` - this will add both items to the scene since blue is now a child of red. If you move red, blue will also move, note that you can still move blue independently of red. Read about the coordinate system here: http://doc.qt.io/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system – dtech Oct 21 '16 at 21:23