mardi 21 avril 2015

copying and moving QGraphicsItem from one QGraphicsScene to another, items snap to (0,0)

I am trying to create items in one panel and add to a second panel. In the second panel I want them to be movable (and have context menu). The AddItem button should add the item from the RenderArea, to the existing list of items in the CollectionView (which may already have been moved)

In the code below, the ShapeView::addItem() is supposed to create a copy of the item from the RenderArea (where it can change shape, color etc but is not movable, starts at (0,0)), place it in the CollectionView, where it is movable. The RenderArea holds one item - once added to CollectionView, the RenderArea item should reset.

What is happening... I can't seem to be able to separate the item from the two classes.

  • When I add item, even if the items in CollectionView have moved, their position resets to 0,0 (or whatever the initial position was in the RenderArea; but the adding works properly, the individual item properties are correct, like shape and color; also - CollectionView items move, RenderArea item doesn't).

I am posting all the relevant code:

class Item : public QGraphicsItem
{
    Item() { setFlag(ItemIsMovable, false); }   
    Item::Item(Item &copyItem) {         // copy constructor
        setFlag(ItemIsMovable); 
        setPos(copyItem.pos());    // doesn't seem to work
    QRectF boundingRect() const { return QRectF(-35, -30, 35, 20); }
    void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) { 
        painter->drawRect(boundingRect()); }

    QPointF p;  // temporary to fix position
protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
        QGraphicsItem::mouseMoveEvent(event);
    }
};

class CollectionView : public QGraphicsView
{
    Q_OBJECT    
public:
    CollectionView(QWidget *parent = 0);    
    void update();
    QList<Item*> *m_items;
};

CollectionView::CollectionView(QWidget *parent)
    : QGraphicsView(parent)
{
    QGraphicsScene *s = new QGraphicsScene(this);
    s->setSceneRect(-this->width()/2, -this->height()/2, this->width()/2, this->height()/2);
    setScene(s);
    setViewportUpdateMode(BoundingRectViewportUpdate);
    m_items = new QList<Item*>();
    scene()->clear();
}

void CollectionView::update()
{
    scene()->clear();
    for(int i = 0; i< m_items->size(); i++)
    {
        Item* item = new Item(*m_items->at(i));
        item->setPos(m_items->at(i)->p);  // doesn't seem to work
        scene()->addItem(item);
    }
    viewport()->update();
}

class RenderArea : public QGraphicsView
{
    Q_OBJECT
public:
    RenderArea(QWidget *parent = 0);    
public:
    Item* item;
};

RenderArea::RenderArea(QWidget *parent)
    : QGraphicsView(parent)
{
    QGraphicsScene *s = new QGraphicsScene(this);
    s->setSceneRect(-this->width()/2, -this->height()/2, this->width()/2, this->height()/2);
    setScene(s);
    setViewportUpdateMode(BoundingRectViewportUpdate);
    item = new Item();
    s->addItem(item);
}

// this is the boss/coordinator class
class ShapeView : public QGraphicsView
{
    Q_OBJECT
public:
    ShapeView(QWidget *parent = 0);
    CollectionView *collectionView;
private slots:    // more slots corresponding to more controls
    void addItem();
private:    
    QPushButton *addButton;
    RenderArea *renderArea;
};

ShapeView::ShapeView(QWidget *parent)
    : QGraphicsView(parent)
{
    collectionView = new CollectionView(parent);
    renderArea = new RenderArea(this);
    addButton = new QPushButton(tr("Add Item"));
    connect(addButton, SIGNAL(clicked()), this, SLOT(addItem()));
}

void ShapeView::addItem()
{   
    Item* item = new Item(*renderArea->item);
    collectionView->m_items->append(item);
    collectionView->update();

    // place a new item on renderarea
    renderArea->item = new Item();
    renderArea->scene()->clear();
    renderArea->scene()->addItem(renderArea->item);
    renderArea->viewport()->update();
}

Something is wrong in either the way I copy the item, I just don't know what. I see no reason why, when adding items, the CollectionView items all snap to the (0,0) position. Perhaps the issue is in the copy constructor but I can't figure what is wrong.

I hope someone can help give me a hint

Update: It seems that the problem is in the CollectionView::update() function... adding a 'delete' at the end of the loop removes the item from the collection... Or in the ShapeView::addItem() function... Am I creating copy of the item or just reusing it ?

But how do I create a copy of the item ?

Aucun commentaire:

Enregistrer un commentaire