在鼠标操作上添加的自定义场景类的QGraphicsRectItem成员会出错

时间:2015-09-22 16:20:02

标签: qt mouseevent qgraphicsitem qgraphicsscene

我想以某种方式在场景上绘制一个选择矩形,以显示所选项目(不是项目边界矩形,而是映射到场景的边界矩形 - 如果是多个选择,则选择边界矩形)。

我想在鼠标按下时尝试显示矩形(并根据当前选择进行更新),并在鼠标释放时隐藏它。

我无法在场景中保留矩形,并且在鼠标释放时它可能正在删除它,或者它可能从未出现过 - 我收到错误:

QGraphicsScene::removeItem: item 0x37828's scene (0x0) is different from this scene (0x1f57b68)

(上面的错误,以及鼠标按下后项目没有停留的事实,让我觉得它没有正确添加,但我不明白为什么)。

以下是一些示例代码:

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>

class MyScene : public QGraphicsScene
{
public:
    MyScene(qreal x, qreal y, qreal w, qreal h) {
        setSceneRect(x, y, w, h);
        m_selectionRectangle = new QGraphicsRectItem(0,0,1,1);
        m_selectionRectangle->setBrush(Qt::magenta);
        m_selectionRectangle->setOpacity(0.2);
    }
    ~MyScene() {
        if(m_selectionRectangle)
            delete m_selectionRectangle;
    }
protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) {
        QGraphicsScene::mousePressEvent(event);
        if(!selectedItems().isEmpty()) {
            QRectF selectionRect = QRectF();
            foreach(QGraphicsItem* item, selectedItems()) 
                selectionRect |= item->mapToScene(item->boundingRect()).boundingRect();
            m_selectionRectangle->setRect(selectionRect);
            addItem(m_selectionRectangle);
        }
    }
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
        QGraphicsScene::mouseReleaseEvent(event);
        removeItem(m_selectionRectangle);
    }
private:
    QGraphicsRectItem* m_selectionRectangle;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyScene* s = new MyScene(0, 0, 800, 600);
    QGraphicsView view(s);
    view.setDragMode(QGraphicsView::RubberBandDrag);
    view.show();
    QGraphicsRectItem* xxx = new QGraphicsRectItem(200, 200, 100, 100);
    QGraphicsEllipseItem* yyy = new QGraphicsEllipseItem(300, 300, 200, 100);
    s->addItem(xxx);
    s->addItem(yyy);
    xxx->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable|QGraphicsItem::ItemIsSelectable);
    yyy->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable|QGraphicsItem::ItemIsSelectable);
    return app.exec();
}

该错误的含义是什么,在添加选择矩形时我做错了什么,为什么不留在那里 - 我该如何解决?

1 个答案:

答案 0 :(得分:0)

错误的含义是字面意思:您将项目传递给removeItem,而该项目不是您尝试将其删除的场景的子项目。删除场景中不在场景中的项目是无稽之谈。

当释放鼠标按钮时,没有什么可以保证选择矩形在场景上,因为有mousePressEvent的路径没有将矩形添加到场景中。我甚至不确定你是否能保证在每次发布活动之前都能获得新闻发布会。

你必须只删除场景中的矩形(并且不需要virtual,但Q_DECL_OVERRIDE是!):

void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE {
  QGraphicsScene::mouseReleaseEvent(event);
  if (m_selectionRectangle.scene()) removeItem(m_selectionRectangle);
}

此外,您的自定义场景的析构函数是不必要的。只需按值添加项目:

class MyScene : public QGraphicsScene
{
    QGraphicsRectItem m_selectionRectangle;
public:
    MyScene(qreal x, qreal y, qreal w, qreal h) :
        m_selectionRectangle(0, 0, 1 1)
    {
        setSceneRect(x, y, w, h);
        m_selectionRectangle.setBrush(Qt::magenta);
        m_selectionRectangle.setOpacity(0.2);
    }
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE {
        ...
    }
    ...
};