Calling width(), height(), size() or rect() inside subclass of QWidget ends with segfault
我对
这是有问题的类的标题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class PlotCanvas : public QWidget { void paintEvent(QPaintEvent * e); uint64_t smallestDiv(); uint64_t longestLength(); void drawGrid(QPainter * painter); QVector<Plot*> plots; int calculateHeight() const; int calculateWidth() const; uint32_t cursorPosition; public: PlotCanvas(QWidget * parent = 0) : QWidget(parent) { setStyleSheet("background-color: black"); setAutoFillBackground(true); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); setFocusPolicy(Qt::StrongFocus); update(); } void addPlot(Plot * plot); int getDivCount(); }; |
和实际的段错误代码:
1 2 3 4 5 6 7 | int PlotCanvas::getDivCount() { QRect bounds = rect(); //segfaults qDebug() << bounds.size().width(); qDebug() << bounds.size().height(); return 10; } |
追溯到Qt的
1 2 | inline int QRect::width() const { return x2 - x1 + 1; } //this line finally kills it |
这似乎是在
1 2 3 4 5 6 7 8 | class PlotCanvasScrollArea : public QAbstractScrollArea { public: PlotCanvasScrollArea(QWidget * parent = 0) : QAbstractScrollArea(parent) { } }; |
我只需要确定
编辑:
构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | Board(QString & name) : name(name) { hbox = new QHBoxLayout(); commonKnobGroup = new QGroupBox("Common settings:"); commonKnobGroup->setMinimumWidth(190); commonKnobGroup->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); commonKnobs = new CommonKnobs(commonKnobGroup); hsplitter = new QSplitter(); plotGroupBox = new QGroupBox("Measurement plots:", hsplitter); settingsGroupBox = new QGroupBox("Plot settings:", hsplitter); plotSplitter = new QSplitter(); plotHbox = new QHBoxLayout(); plotHbox->addWidget(plotSplitter); plotGroupBox->setLayout(plotHbox); settingsVLayout = new QVBoxLayout(); plotNamesColumn = new QListWidget(plotSplitter); scrollArea = new PlotCanvasScrollArea(plotSplitter); //scrollArea->setWidgetResizable(true); plotsCanvas = new PlotCanvas(); scrollArea->setViewport(plotsCanvas); scrollArea->setBackgroundRole(QPalette::Dark); specializedKnobGroup = new QGroupBox("Probe settings:"); plotSettings = new QStackedWidget(specializedKnobGroup); settingsVLayout->addWidget(commonKnobGroup); settingsVLayout->addWidget(specializedKnobGroup); settingsGroupBox->setLayout(settingsVLayout); hbox->addWidget(hsplitter); setLayout(hbox); connect(plotNamesColumn, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePageNames(QListWidgetItem*, QListWidgetItem*))); connect(commonKnobs, SIGNAL(scaleUpdated()), plotsCanvas, SLOT(update())); }; |
编辑2:
完整的堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #0 0x000000010000b9ac in QWidget::rect() const at /Volumes/Data/shinji/QtSDK/Desktop/Qt/474/gcc/include/QtGui/qwidget.h:1007 #1 0x000000010000b454 in PlotCanvas::getDivCount() () #2 0x000000010000ab39 in Board::getDivCount() () #3 0x0000000100009fbc in CommonKnobs::updateScaleByBeginEnd() () #4 0x00000001000015b4 in CommonKnobs::qt_metacall(QMetaObject::Call, int, void**) () #5 0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () #6 0x000000010070df9d in QSpinBox::valueChanged(int) () #7 0x00000001004d9684 in QSpinBoxPrivate::emitSignals(EmitPolicy, QVariant const&) () #8 0x000000010043b321 in QAbstractSpinBoxPrivate::setValue(QVariant const&, EmitPolicy, bool) () #9 0x000000010043c11a in QAbstractSpinBoxPrivate::_q_editorTextChanged(QString const&) () #10 0x000000010043cca7 in QAbstractSpinBox::qt_metacall(QMetaObject::Call, int, void**) () #11 0x000000010070e435 in QSpinBox::qt_metacall(QMetaObject::Call, int, void**) () #12 0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () #13 0x000000010048a1e6 in QLineEdit::textChanged(QString const&) () #14 0x000000010048d23a in QLineEdit::qt_metacall(QMetaObject::Call, int, void**) () #15 0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () #16 0x000000010070c9f9 in QLineControl::textChanged(QString const&) () #17 0x0000000100494337 in QLineControl::finishChange(int, bool, bool) () #18 0x0000000100496664 in QLineControl::processKeyEvent(QKeyEvent*) () #19 0x000000010048b8eb in QLineEdit::keyPressEvent(QKeyEvent*) () #20 0x00000001001056bd in QWidget::event(QEvent*) () #21 0x000000010048c18b in QLineEdit::event(QEvent*) () #22 0x000000010043d9f0 in QAbstractSpinBox::keyPressEvent(QKeyEvent*) () #23 0x00000001001056bd in QWidget::event(QEvent*) () #24 0x000000010043bb1b in QAbstractSpinBox::event(QEvent*) () #25 0x00000001004d7be5 in QSpinBox::event(QEvent*) () #26 0x00000001000a9e8d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () #27 0x00000001000b198b in QApplication::notify(QObject*, QEvent*) () #28 0x0000000100d0321c in QCoreApplication::notifyInternal(QObject*, QEvent*) () #29 0x00000001000a9f2c in qt_sendSpontaneousEvent(QObject*, QEvent*) () #30 0x0000000100125cc1 in QKeyMapper::sendKeyEvent(QWidget*, bool, QEvent::Type, int, QFlags<Qt::KeyboardModifier>, QString const&, bool, int, unsigned int, unsigned int, unsigned int, bool*) () #31 0x0000000100126b43 in QKeyMapperPrivate::translateKeyEvent(QWidget*, OpaqueEventHandlerCallRef*, OpaqueEventRef*, void*, bool) () #32 0x000000010006072e in qt_dispatchKeyEvent(void*, QWidget*) () #33 0x000000010005478b in -[QCocoaView keyDown:] () #34 0x00007fff815a90c7 in -[NSWindow sendEvent:] () #35 0x0000000100059891 in -[QCocoaWindow sendEvent:] () #36 0x00007fff814ddafa in -[NSApplication sendEvent:] () #37 0x000000010005cf0a in -[QNSApplication sendEvent:] () #38 0x00007fff814746de in -[NSApplication run] () #39 0x0000000100066c04 in QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () #40 0x0000000100def774 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () #41 0x0000000100defa94 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () #42 0x0000000100df10bc in QCoreApplication::exec() () #43 0x0000000100001cf6 in main () |
我已经整理好了,它使用 parent() 作为指向 Board 的指针(使用 scatic_cast 进行投射,我认为使用 static_cast 投射到错误的对象会在那时杀死它,但不是)来自 PlotCanvas 和我的另一个类使用,当实际上 parent() 在 PlotCanvas 和 QGroupBox 的情况下引用到 PlotCanvasScrollArea 时,在其他类的情况下。
奇怪的是,调试器显示我实际上跳入了 Board\\ 的代码,即使认为被调用对象的地址完全错误,更奇怪的是它在 PlotCanvas 代码中崩溃而不是原始代码(Board\\ 的代码)。
但现在没事了。谢谢各位:)
尝试使用小部件
请参阅 Qt 窗口几何文档。
您的 scrollArea 是作为 plotSplitter 的子级创建的,但它永远不会使用 addWidget() 添加到拆分器中,此外 plotSplitter 没有父级,这意味着它将是它自己的窗口。我想问题可能出在您将 scrollArea 的视口设置为 plotsCanvas 时,这是另一个没有父级的 QWidget,因此也没有自己的窗口。
尝试这样的事情并从那里开始工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Board(QString & name) : name(name) { hbox = new QHBoxLayout(); commonKnobGroup = new QGroupBox("Common settings:"); commonKnobGroup->setMinimumWidth(190); commonKnobGroup->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); commonKnobs = new CommonKnobs(commonKnobGroup); hsplitter = new QSplitter(); plotGroupBox = new QGroupBox("Measurement plots:", hsplitter); settingsGroupBox = new QGroupBox("Plot settings:", hsplitter); plotSplitter = new QSplitter(this); plotHbox = new QHBoxLayout(); plotHbox->addWidget(plotSplitter); plotGroupBox->setLayout(plotHbox); settingsVLayout = new QVBoxLayout(); plotNamesColumn = new QListWidget(plotSplitter); scrollArea = new PlotCanvasScrollArea(plotSplitter); plotSplitter->addWidget(plotNamesColumn); plotSplitter->addWidget(scrollArea); //scrollArea->setWidgetResizable(true); plotsCanvas = new PlotCanvas(this); scrollArea->setViewport(plotsCanvas); scrollArea->setBackgroundRole(QPalette::Dark); specializedKnobGroup = new QGroupBox("Probe settings:"); plotSettings = new QStackedWidget(specializedKnobGroup); settingsVLayout->addWidget(commonKnobGroup); settingsVLayout->addWidget(specializedKnobGroup); settingsGroupBox->setLayout(settingsVLayout); hbox->addWidget(hsplitter); setLayout(hbox); connect(plotNamesColumn, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePageNames(QListWidgetItem*, QListWidgetItem*))); connect(commonKnobs, SIGNAL(scaleUpdated()), plotsCanvas, SLOT(update())); }; |
查看崩溃堆栈跟踪 - 它是否会导致某个地方的构造函数?我的第一个想法是,我不确定您是否应该在构造函数中调用 update - 我可能不在基地,但这对我来说似乎是错误的。如果 update 应该在 QWidget 构造函数中调用,那么基本构造函数将调用它(使您的调用变得多余),如果不应该,那么我完全不清楚会发生什么。