Член QGraphicsRectItem пользовательского класса сцены, добавленный при действии мыши, дает ошибку

Я хочу как-то нарисовать прямоугольник выбора на сцене, чтобы показать выбранные элементы (не прямоугольник, ограничивающий элемент, а ограничивающий прямоугольник, сопоставленный со сценой, а при множественном выборе - ограничивающий прямоугольник выделения).

Я хотел бы попробовать что-то вроде нажатия мыши, чтобы показать прямоугольник (и обновить на основе текущего выбора), а при отпускании мыши, чтобы скрыть его.

У меня возникли проблемы с сохранением прямоугольника на сцене, и при отпускании мыши он может удалить его, или, может быть, его никогда не было - и я получаю сообщение об ошибке:

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();
}

В чем смысл этой ошибки, что я делаю неправильно при добавлении прямоугольника выбора и почему он не остается там - и как я могу это исправить?


person Thalia    schedule 22.09.2015    source источник


Ответы (1)


Значение ошибки буквальное: вы передаете элемент 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 {
        ...
    }
    ...
};
person Kuba hasn't forgotten Monica    schedule 22.09.2015