C++ 使用QGraphicsEffect删除QGraphicsItem会导致segfault
以下程序绘制红色背景。按下鼠标左键可在其上绘制一个白色矩形。该矩形有一个子矩形和一个C++ 使用QGraphicsEffect删除QGraphicsItem会导致segfault,c++,qt,qgraphicsitem,C++,Qt,Qgraphicsitem,以下程序绘制红色背景。按下鼠标左键可在其上绘制一个白色矩形。该矩形有一个子矩形和一个QGraphicsDropShadowEffect。(QGraphicsOpacityEffect和QGraphicsColorizeEffect也会导致该问题,但频率较低。) 按鼠标右键可删除白色矩形 有时删除矩形会导致分割错误 如果未应用QGraphicsDropShadowEffect,则不会发生这种情况。如果MyRect中没有子项,或者后台被复制,也不会发生这种情况 (在搜索此问题时,我发现了一些提示,表
QGraphicsDropShadowEffect
。(QGraphicsOpacityEffect
和QGraphicsColorizeEffect
也会导致该问题,但频率较低。)
按鼠标右键可删除白色矩形
有时删除矩形会导致分割错误
如果未应用QGraphicsDropShadowEffect
,则不会发生这种情况。如果MyRect
中没有子项,或者后台被复制,也不会发生这种情况
(在搜索此问题时,我发现了一些提示,表明像这样的segfault可能与在不调用prepareGeometryChange()
的情况下更改项的boundingRect()
有关)
我在这里真是不知所措。这是一个更大项目的一部分,我将其归结为以下示例:
Main.cc:
#include<QApplication>
#include<QGraphicsView>
#include<QGraphicsScene>
#include<QGraphicsSceneMouseEvent>
#include<QGraphicsRectItem>
#include<QGraphicsDropShadowEffect>
#include<QScreen>
class MyRect: public QGraphicsRectItem
{
public:
MyRect(QGraphicsItem* parent = nullptr):
QGraphicsRectItem{QRectF{0.0f, 0.0f, 100.0f, 100.0f}, parent}
{
setPen(QPen{Qt::white});
setBrush(QBrush{Qt::white, Qt::SolidPattern});
my_child_=new QGraphicsRectItem{this};
}
private:
QGraphicsRectItem* my_child_=nullptr;
};
class MyScene: public QGraphicsScene
{
public:
MyScene()
{
background_=new QGraphicsRectItem{0.0f, 0.0f, 500.0f, 500.0f};
background_->setPen(QPen{Qt::white});
background_->setBrush(QBrush{Qt::red, Qt::SolidPattern});
addItem(background_);
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent* me) override
{
if (me->button()==Qt::LeftButton)
{
if (my_rect_==nullptr)
{
my_rect_=new MyRect{};
shadow_=new QGraphicsDropShadowEffect{};
shadow_->setBlurRadius(15.0f);
my_rect_->setGraphicsEffect(shadow_);
addItem(my_rect_);
my_rect_->setPos(me->scenePos());
}
}
else if (me->button()==Qt::RightButton)
{
if (my_rect_!=nullptr)
{
removeItem(my_rect_);
my_rect_->setGraphicsEffect(0);
shadow_=nullptr;
delete my_rect_;
my_rect_=nullptr;
}
}
else
{
QGraphicsScene::mouseReleaseEvent(me);
}
}
private:
QGraphicsRectItem* background_=nullptr;
MyRect* my_rect_=nullptr;
QGraphicsDropShadowEffect* shadow_=nullptr;
};
int
main(int argc, char** argv)
{
QApplication qapp{argc, argv};
QGraphicsView view;
MyScene scene;
QRect rect=QGuiApplication::primaryScreen()->geometry();
scene.setSceneRect(0.0f, 0.0f, rect.width(), rect.height());
view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.setFrameShape(QFrame::NoFrame);
view.setBackgroundBrush(QBrush(Qt::black, Qt::SolidPattern));
view.setScene(&scene);
view.showFullScreen();
return qapp.exec();
}
回溯:
#0 0x0000555555a9a840 in ?? ()
#1 0x00007ffff71e017c in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#2 0x00007ffff71e0a3a in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#3 0x00007ffff720289a in QGraphicsView::paintEvent(QPaintEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#4 0x00007ffff6f10278 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#5 0x00007ffff6ff89fe in QFrame::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#6 0x00007ffff72013ab in QGraphicsView::viewportEvent(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#7 0x00007ffff7650701 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#8 0x00007ffff6ec8b65 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#9 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#10 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#11 0x00007ffff6f08fda in QWidgetPrivate::sendPaintEvent(QRegion const&) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#12 0x00007ffff6f09646 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#13 0x00007ffff6ed8f1e in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#14 0x00007ffff6ed9147 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#15 0x00007ffff6ef7f8f in QWidgetPrivate::syncBackingStore() () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#16 0x00007ffff6f10348 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#17 0x00007ffff6ff89fe in QFrame::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007ffff7081de3 in QAbstractScrollArea::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#19 0x00007ffff6ec8b8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#20 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#21 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#22 0x00007ffff765312d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#23 0x00007ffff71d2a22 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007ffff71d8299 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x00007ffff767d459 in QObject::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#26 0x00007ffff71e4e6b in QGraphicsScene::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#27 0x00007ffff6ec8b8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#28 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#29 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#30 0x00007ffff765312d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#31 0x00007ffff76a4c03 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#32 0x00007ffff446f7f7 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#33 0x00007ffff446fa60 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#34 0x00007ffff446fb0c in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#35 0x00007ffff76a500f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#36 0x00007ffff764e98a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#37 0x00007ffff76570fc in QCoreApplication::exec() () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#38 0x000055555555768b in main (argc=1, argv=0x7fffffffe5b8) at Main.cc:89
#0 0x000055555A9A840英寸??()
#1 0x00007FF71E017C英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#2 0x00007FF71E0A3A英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QGraphicsView::paintEvent(QPaintEvent*)()中的3 0x00007ffff720289a
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QWidget::event(QEvent*)()中的4 0x00007ffff6f10278
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QFrame::event(QEvent*)()中的5 0x00007ffff6ff89fe
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QGraphicsView::viewportEvent(QEvent*)()中的6 0x00007FF72013ab
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*,QEvent*)()中的7 0x00007FF7650701
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so的QApplicationPrivate::notify_helper(QObject*,QEvent*)()中的8 0x00007ffff6ec8b65。5
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so的QApplication::notify(QObject*,QEvent*)()中的9 0x00007ffff6ed0341
#10 0x00007FF76509A0在/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplication::notifyInternal2(QObject*,QEvent*)中
#11/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5中QWidgetPrivate::sendPaintEvent(QRegion const&)中的0x00007ffff6f08fda
#QWidgetPrivate::drawWidget中的12 0x00007ffff6f09646(QPaintDevice*、QRegion const&、QPoint const&、int、QPainter*、QWidgetBackingStore*)()
来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#13 0x00007ffff6ed8f1e英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#14 0x00007ffff6ed9147英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QWidgetPrivate::syncBackingStore()中的15 0x00007ffff6ef7f8f
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QWidget::event(QEvent*)()中的16 0x00007ffff6f10348
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QFrame::event(QEvent*)()中的17 0x00007ffff6ff89fe
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QAbstractScrollArea::event(QEvent*)()中的18 0x00007ffff7081de3
#19/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5中QApplicationPrivate::notify_helper(QObject*,QEvent*)()中的0x00007ffff6ec8b8c
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QApplication::notify(QObject*,QEvent*)()中的20 0x00007ffff6ed0341
#21 0x00007FF76509A0在/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplication::notifyInternal2(QObject*,QEvent*)中
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplicationPrivate::sendPostedEvents(QObject*,int,QThreadData*))中的22 0x00007FF765312d
#23 0x00007FF71D2A22英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007FF71D8299英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QObject::event(QEvent*)()中的25 0x00007ff767d459
#26/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5中qgraphicscene::event(QEvent*)()中的0x00007ff71e4e6b
#QApplicationPrivate::notify_helper(QObject*,QEvent*)中的27 0x00007ffff6ec8b8c,来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#来自/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5的QApplication::notify(QObject*,QEvent*)()中的28 0x00007ffff6ed0341
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplication::notifyInternal2(QObject*,QEvent*)中的29 0x00007ff76509a0
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplicationPrivate::sendPostedEvents(QObject*,int,QThreadData*))中的30 0x00007FF765312d
#31 0x00007FF76A4C03英寸??()来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#32 0x00007FF446F7位于/lib/x86\u 64-linux-gnu/libglib-2.0.so.0的g_主上下文中
#33 0x00007FF446FA60英寸??()来自/lib/x86_64-linux-gnu/libglib-2.0.so.0
#34 0x00007FF446FB0C位于/lib/x86\u 64-linux-gnu/libglib-2.0.so.0中的g_主上下文迭代()中
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QEventDispatcherGlib::processEvents(QFlags)()中的35 0x00007ff76a500f
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QEventLoop::exec(QFlags)()中的36 0x00007ffff764e98a
#来自/usr/lib/x86_64-linux-gnu/libQt5Core.so.5的QCoreApplication::exec()中的37 0x00007FF76570fc
#干管中的38 0x0000555768B(argc=1,argv=0x7fffffe5b8)位于干管中。cc:89
编辑:为了更好的可读性,我重新编写了代码示例。因为我接受了关于这不是预期行为的教育,可能是Qt中的错误
最好的解决方法是在将其从场景中删除之前,在my_rect
上调用QGraphicsItem::prepareGeometryChange()
。这可以通过公开受保护的prepareGeometryChange()
或在~MyRect()
内调用它,然后简单地删除MyRect
,而不调用qgraphicscenscene::removietem()
~QGraphicsItem()
,当然是在~MyRect()
之后调用,它将
#0 0x0000555555a9a840 in ?? ()
#1 0x00007ffff71e017c in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#2 0x00007ffff71e0a3a in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#3 0x00007ffff720289a in QGraphicsView::paintEvent(QPaintEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#4 0x00007ffff6f10278 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#5 0x00007ffff6ff89fe in QFrame::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#6 0x00007ffff72013ab in QGraphicsView::viewportEvent(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#7 0x00007ffff7650701 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#8 0x00007ffff6ec8b65 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#9 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#10 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#11 0x00007ffff6f08fda in QWidgetPrivate::sendPaintEvent(QRegion const&) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#12 0x00007ffff6f09646 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#13 0x00007ffff6ed8f1e in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#14 0x00007ffff6ed9147 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#15 0x00007ffff6ef7f8f in QWidgetPrivate::syncBackingStore() () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#16 0x00007ffff6f10348 in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#17 0x00007ffff6ff89fe in QFrame::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007ffff7081de3 in QAbstractScrollArea::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#19 0x00007ffff6ec8b8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#20 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#21 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#22 0x00007ffff765312d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#23 0x00007ffff71d2a22 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007ffff71d8299 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x00007ffff767d459 in QObject::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#26 0x00007ffff71e4e6b in QGraphicsScene::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#27 0x00007ffff6ec8b8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#28 0x00007ffff6ed0341 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#29 0x00007ffff76509a0 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#30 0x00007ffff765312d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#31 0x00007ffff76a4c03 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#32 0x00007ffff446f7f7 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#33 0x00007ffff446fa60 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#34 0x00007ffff446fb0c in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#35 0x00007ffff76a500f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#36 0x00007ffff764e98a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#37 0x00007ffff76570fc in QCoreApplication::exec() () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#38 0x000055555555768b in main (argc=1, argv=0x7fffffffe5b8) at Main.cc:89