自定义场景 class 的 QGraphicsRectItem 成员添加到鼠标操作时会出错
QGraphicsRectItem member of a custom scene class added on mouse action gives error
我想以某种方式在场景上绘制一个选择矩形,以显示所选项目(不是他的项目边界矩形,而是映射到场景的边界矩形 - 如果有多个选择,则为选择边界矩形)。
我想尝试在按下鼠标时显示矩形(并根据当前选择进行更新),在松开鼠标时隐藏它。
我无法将矩形保留在场景中,松开鼠标时它可能会移除它,或者它可能根本不存在 - 我收到错误消息:
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();
}
该错误的含义是什么,我在添加选择矩形时做错了什么,为什么它不留在那里 - 我该如何解决?
错误的含义是字面意思:您正在将一个项目传递给 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 {
...
}
...
};
我想以某种方式在场景上绘制一个选择矩形,以显示所选项目(不是他的项目边界矩形,而是映射到场景的边界矩形 - 如果有多个选择,则为选择边界矩形)。
我想尝试在按下鼠标时显示矩形(并根据当前选择进行更新),在松开鼠标时隐藏它。
我无法将矩形保留在场景中,松开鼠标时它可能会移除它,或者它可能根本不存在 - 我收到错误消息:
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();
}
该错误的含义是什么,我在添加选择矩形时做错了什么,为什么它不留在那里 - 我该如何解决?
错误的含义是字面意思:您正在将一个项目传递给 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 {
...
}
...
};