将QGraphicsItem从一个QGraphicsScene复制到另一个,项目捕捉到(0,0)

时间:2015-04-20 19:26:49

标签: c++ qt drawing copy-constructor

我正在尝试在一个面板中创建项目并添加到第二个面板。在第二个面板中,我希望它们可以移动(并具有上下文菜单)。 AddItem按钮应该将RenderArea中的项目添加到CollectionView中的项目的现有列表中(可能已经移动了)

在下面的代码中,ShapeView::addItem()应该从RenderArea创建项目的副本(它可以改变形状,颜色等但不能移动,从(0,0)开始),地方它在CollectionView,它可以移动。 RenderArea包含一个项目 - 一旦添加到CollectionViewRenderArea项目就会重置。

发生了什么......我似乎无法将该项与两个类分开。

  • 当我添加项目时,即使项目在 CollectionView已移动,其位置重置为0,0(或RenderArea中的初始位置;但添加 工作正常,个别项目属性是正确的,如形状和颜色;另外 - CollectionView项目移动,RenderArea项目 不)。

我发布了所有相关代码:

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()); }
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(-width()/2, -height()/2, width(), height());
    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(-width()/2, -height()/2, width(), height());
    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();
}

我复制项目的方式都有问题,我只是不知道是什么。我没有理由在添加项目时,CollectionView项都会捕捉到(0,0)位置。也许问题出在复制构造函数中,但我无法弄清楚是什么问题。

我希望有人可以帮我一个提示

更新:似乎问题出现在CollectionView::update()函数中...在循环结束时添加'删除'会从集合中删除项目...或者在ShapeView::addItem()函数中...我是在创建项目的副本还是只是重用它?

但是如何创建项目的副本?

1 个答案:

答案 0 :(得分:0)

我的假设是我在QGraphicsScene上绘制的项目与它们的表示(作为指向对象的指针)之间存在联系。错......实际上我误解了指针指向的是什么......

我在鼠标移动后更新了列表中项目的位置,一切都很好。

void CollectionView::mouseMoveEvent(QMouseEvent *event)
{
    Item *currentItem = (Item*)itemAt(event->pos().x(), event->pos().y());
    if(!currentItem) return;    
    QGraphicsView::mouseMoveEvent(event);   
    m_items->at(currentItem->z)->setPos(currentItem->pos());
}

以上修复了显示的代码。但这不是最好的解决办法。

问题的更好解决方案 - 完全删除我的项目列表,因为QGraphicsScene已经拥有副本。 (处理我自己的项目列表有一个好处 - 物品的bringForward和sendBackward更容易实现,因为我的z值等于项目索引)