Использование QWidget *QLayoutItem::widget() вызывает ошибку сегмента (в qobjectdefs_impl.h)

Я использую QTabWidget внутри вкладок QTabWidget, и когда я пытаюсь получить «дочерний» QTabWidget, который хранится в макете вкладки «родительского» QTabWidget, у меня возникает ошибка сегмента.

PS: я использую Qt Creator v4.8.1, Qtv5.6.3 и 64-битную ОС Windows 7 (VM под VBox v6.0.4)

Изначально следующая строка выдает ошибку

dbTablesTabWidget = static_cast<QTabWidget*>(ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget());

Я пробовал без "static_cast" со следующей строкой, но ошибка всегда здесь

QWidget *widget = ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget();

Моя последняя попытка (без возврата указателя QWidget) всегда с одной и той же ошибкой «ошибка сегмента».

ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget();

Я не понимаю, что следующая строка (первая строка в первом цикле for)

QString itemClass = ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget()->metaObject()->className();

работает нормально, хотя включает тот же «базовый код».

В файле «qobjectdefs_impl.h» появляется ошибка сегмента:

1   MainWindow::addRow                                                                                                                                        mainwindow.cpp          298  0x403de6   
2   QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (MainWindow:: *)()>::call(void (MainWindow:: *)(), MainWindow *, void * *) qobjectdefs_impl.h      501  0x410175   
3   QtPrivate::FunctionPointer<void (MainWindow:: *)()>::call<QtPrivate::List<>, void>(void (MainWindow:: *)(), MainWindow *, void * *)                       qobjectdefs_impl.h      520  0x4103e2   
4   QtPrivate::QSlotObject<void (MainWindow:: *)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void * *, bool *)            qobject_impl.h          143  0x410243   
5   QtPrivate::QSlotObjectBase::call                                                                                                                          qobject_impl.h          124  0x6ba5d241 
6   QMetaObject::activate                                                                                                                                     qobject.cpp             3715 0x6b8fc213 
7   QMetaObject::activate                                                                                                                                     qobject.cpp             3595 0x6b8fbc3e 
8   QAbstractButton::clicked                                                                                                                                  moc_qabstractbutton.cpp 307  0x9c0685   
9   QAbstractButtonPrivate::emitClicked                                                                                                                       qabstractbutton.cpp     404  0x9be459   
10  QAbstractButtonPrivate::click                                                                                                                             qabstractbutton.cpp     397  0x9be3f4   
11  QAbstractButton::mouseReleaseEvent                                                                                                                        qabstractbutton.cpp     1002 0x9bf6f7   
12  QWidget::event                                                                                                                                            qwidget.cpp             8757 0x8f6881   
13  QAbstractButton::event                                                                                                                                    qabstractbutton.cpp     959  0x9bf56c   
14  QPushButton::event                                                                                                                                        qpushbutton.cpp         673  0xa55168   
15  QApplicationPrivate::notify_helper                                                                                                                        qapplication.cpp        3804 0x8bf880   
16  QApplication::notify                                                                                                                                      qapplication.cpp        3277 0x8bd5f1   
17  QCoreApplication::notifyInternal2                                                                                                                         qcoreapplication.cpp    1015 0x6b8d37dd 
18  QCoreApplication::sendSpontaneousEvent                                                                                                                    qcoreapplication.h      228  0xc2fb5d   
19  QApplicationPrivate::sendMouseEvent                                                                                                                       qapplication.cpp        2773 0x8bc2cb   
20  QWidgetWindow::handleMouseEvent                                                                                                                           qwidgetwindow.cpp       607  0x90f314   
... <plus>                                                                                                                                                                                            

Ниже выдержка из метода addRow («пользовательский» приватный слот, вызываемый после нажатия кнопки QPushButton)

// var
    int dbIndex = ui->tabWidget->currentIndex();
    int tableIndex = 0;
    QTabWidget *dbTablesTabWidget;

    // Détection de l'index de l'item du layout de l'onglet de la BDD actuellement sélectionné
    // -> Détection de la position du widget (jeu d'onglets des tables) dans le layout pour récupérer l'index de la table actuelle.
    for (int i=0; i<ui->tabWidget->currentWidget()->layout()->count(); i++)
    {
        QString itemClass = ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget()->metaObject()->className();
        qDebug(itemClass.toLatin1());
        if (itemClass == "QTabWidget")
        {
            qDebug("Cet élément est un QTabWidget !!!");

            //*** The following line throws a segment fault ***

            //dbTablesTabWidget = static_cast<QTabWidget*>(ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget());
            //QWidget *widget = ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget();
            ui->tabWidget->currentWidget()->layout()->takeAt(i)->widget();

            tableIndex = dbTablesTabWidget->currentIndex();
        }
    }

Я новичок в Qt и не понимаю, откуда может появиться ошибка сегмента. Процесс компиляции в порядке, см. ниже (версия на французском языке)

15:53:12: Configuration inchangée, étape qmake sautée.
15:53:12: Débute : "C:\Qt\Tools\mingw492_32\bin\mingw32-make.exe" -j1
C:/Qt/Tools/mingw492_32/bin/mingw32-make -f Makefile.Debug
mingw32-make[1]: Entering directory 'E:/Projects_Info_Slink/_Training/C++/QTCreatorProject/DataBaseViewerGUI/build-DataBaseViewerGUI-Desktop_Qt_5_6_3_MinGW_32bit-Debug'
mingw32-make[1]: Nothing to be done for 'first'.
mingw32-make[1]: Leaving directory 'E:/Projects_Info_Slink/_Training/C++/QTCreatorProject/DataBaseViewerGUI/build-DataBaseViewerGUI-Desktop_Qt_5_6_3_MinGW_32bit-Debug'
15:53:13: Le processus "C:\Qt\Tools\mingw492_32\bin\mingw32-make.exe" s'est terminé normalement.
15:53:13: Temps écoulé : 00:01.

person ManWithNoName    schedule 08.02.2019    source источник


Ответы (2)


Ваша страница в tabwidget может иметь любой виджет вместе с виджетом дочерней вкладки.

Для простоты, возможно, вы можете попробовать следующий способ:

//GET YOUR CURRENT PAGE IN FIRST TAB WIDGET
QWidget *widget = ui->tabWidget->currentWidget();

//FROM THE CURRENT PAGE FIND THE CHILD TAB WIDGETS
QList<QTabWidget*> tabWidgets = widget->findChildren<QTabWidget*>();

//USE THE FOUND WIDGET FOR YOUR PURPOSE. DO SOME SAFETY CHECKS FOR LIST.
QTabWidget* requiredTabWidget = tabWidgets[0];
person Pavan Chandaka    schedule 08.02.2019
comment
Я использую макет внутри каждой вкладки, поэтому я не могу напрямую получить какие-либо дочерние элементы QWidget (вместо этого элемент QLayout). Без использования макета, я думаю, ваше решение может быть обходным путем! - person ManWithNoName; 08.02.2019
comment
Я думаю, что это должно работать, даже если макет есть. Не могли бы вы попробовать один раз. - person Pavan Chandaka; 08.02.2019

Наконец-то я нашел ошибку: я должен использовать layout()->itemAt(i) вместо layout()->takeAt(i). Это объясняет, почему ошибка возникает во второй раз. takeAt удалить элемент из списка, чтобы при следующем вызове элемент не существовал в списке.

PS: для объекта QList это at вместо itemAt, чтобы получить элемент из списка элементов.

person ManWithNoName    schedule 08.02.2019