以下程序描绘了红色背景。按下鼠标左键会在其上绘制一个白色矩形。矩形有一个子矩形和一个QGraphicsDropShadowEffect
。 (QGraphicsOpacityEffect
和QGraphicsColorizeEffect
也会导致问题,但不太常见。)
按鼠标右键将删除白色矩形。
有时删除矩形会导致分段错误。
如果未应用QGraphicsDropShadowEffect
,则不会发生这种情况。当MyRect
中没有子项或者背景被忽略时,也不会发生这种情况。
(在搜索此问题时,我发现了一些暗示,这样的段错误可能与更改项目的boundingRect()
而不调用prepareGeometryChange()
有关。)
我真的很茫然。这是一个更大项目的一部分,我将其归结为以下示例:
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();
}
编译器调用:
g++ --std=c++14 -fPIC -Wall -Woverloaded-virtual -Werror -pedantic -g -O0 -fPIC -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -o test Main.cc -lQt5Gui -lQt5Core -lQt5Widgets
回溯:
#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 :(得分:1)
由于我受过on the Qt forums教育,这不是预期的行为,可能是Qt中的错误。
最佳解决方法是在<{1}} 之前调用QGraphicsItem::prepareGeometryChange()
从场景中删除它。这可以通过公开受保护的my_rect_
或在prepareGeometryChange()
内调用它,然后只是删除~MyRect()
而不调用my_rect_
来完成。 QGraphicsScene::removeItem()
,当然在~QGraphicsItem()
之后调用,会自动从场景中删除该项目。