Solved Crash using QListWidget
-
Good afternoon,
I am having problems with a widget. The widget and its code is as follows:

Below the "+" and "-" buttons there are 2 QListWidget where custom widgets are inserted, being these QListWidget as follows:

The problem comes that when I try to add a new widget to the QListWidget, it crashes and closes everything. I have managed to find out that when they are going to insert the widget in one of the lists, the memory address of the lists has changed and that's where the crashes come from. But I can't understand the reason. And Image of problem:

The code is the following:
DataTypeListWidget.h
#ifndef DATATYPELISTWIDGET_H #define DATATYPELISTWIDGET_H #include <QWidget> #include <QListWidget> #include <QListWidgetItem> #include "ItemDataTypeWidget.h" class DataTypeListWidget : public QWidget { Q_OBJECT public: DataTypeListWidget( QWidget* parent = nullptr ); void AddNewWidget( QWidget* newWidget ); public: QListWidget* _list; QHBoxLayout* layout; }; #endif // DATATYPELISTWIDGET_H
DataTypeListWidget.cpp
#include "DataTypeListWidget.h" #include <QDebug> DataTypeListWidget::DataTypeListWidget(QWidget *parent) : QWidget( parent ) , _list( new QListWidget( this ) ) { layout = new QHBoxLayout( ); layout->addWidget( _list ); } void DataTypeListWidget::AddNewWidget(QWidget *newWidget ) { QListWidgetItem* item = new QListWidgetItem( ); _list->insertItem( _list->count(), item ); item->setSizeHint( newWidget->sizeHint() ); _list->setItemWidget( item, newWidget ); layout->setSizeConstraint( QLayout::SetFixedSize ); this->setMinimumSize( layout->sizeHint() ); }
SceneContainerConfigWindow.h
#ifndef SCENECONTAINERCONFIGWINDOW_H #define SCENECONTAINERCONFIGWINDOW_H #include <QWidget> #include <QPushButton> #include <QLabel> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGridLayout> #include "DataTypeListWidget.h" #include "QDebug" class SceneContainerConfigWindow : public QWidget { Q_OBJECT public: explicit SceneContainerConfigWindow( QWidget* parent = nullptr ); void BuildWidget(); void BuildLogic(); public slots: void AddInput(); void AddOutput(); protected: ItemDataTypeWidget* MakeNewItem( int pos, QStringList options ); protected: QPushButton* apply; QPushButton* cancel; QPushButton* add_input; QPushButton* add_output; QPushButton* delete_input; QPushButton* delete_output; DataTypeListWidget* inputs_list; int _input_count; DataTypeListWidget* outputs_list; int _output_count; QLabel* input_label; QLabel* output_label; QHBoxLayout* actionsbuttons_layouts; QHBoxLayout* inputs_labes_layouts; QHBoxLayout* listwidgets_layouts; QHBoxLayout* add_delete_itemsList_layout; QGridLayout* p_layout; QVBoxLayout* main_layout; QStringList _options; }; #endif // SCENECONTAINERCONFIGWINDOW_H
SceneContainerConfigWindow.cpp
#include "SceneContainerConfigWindow.h" SceneContainerConfigWindow::SceneContainerConfigWindow(QWidget *parent) : QWidget( parent ) , _input_count( 0 ), _output_count( 0 ) { BuildWidget(); BuildLogic(); } void SceneContainerConfigWindow::BuildWidget() { _options << "decimal" << "string"; // First widgets level input_label = new QLabel( " INPUTS ", this ); output_label = new QLabel( " OUTPUTS ", this ); // Second widgets level add_input = new QPushButton( this ); delete_input = new QPushButton( this ); add_output = new QPushButton( this ); delete_output = new QPushButton( this ); p_layout = new QGridLayout(); p_layout->addWidget( input_label, 0, 0, 1, 2 ); p_layout->addWidget( output_label, 0, 2, 1, 2 ); p_layout->addWidget( add_input, 1, 0, 1, 1 ); p_layout->addWidget( delete_input, 1, 1, 1, 1 ); p_layout->addWidget( add_output, 1, 2, 1, 1 ); p_layout->addWidget( delete_output, 1, 3, 1, 1 ); // Thirst widgets level DataTypeListWidget* inputs_list = new DataTypeListWidget( this ); DataTypeListWidget* outputs_list = new DataTypeListWidget( this ); inputs_list->setMinimumSize( 200, 300 ); inputs_list->setMaximumSize( 5000, 5000 ); inputs_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); outputs_list->setMinimumSize( 200, 300 ); outputs_list->setMaximumSize( 5000, 5000 ); outputs_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); listwidgets_layouts = new QHBoxLayout(); listwidgets_layouts->addWidget( inputs_list ); listwidgets_layouts->addWidget( outputs_list ); // Four widgets level apply = new QPushButton( "APPLY", this ); cancel = new QPushButton( "CANCEL", this ); actionsbuttons_layouts = new QHBoxLayout(); actionsbuttons_layouts->addSpacing( 150 ); actionsbuttons_layouts->addWidget( cancel ); actionsbuttons_layouts->addWidget( apply ); // Adding all layout to widget main_layout = new QVBoxLayout(); main_layout->addLayout( p_layout ); main_layout->addLayout( listwidgets_layouts ); main_layout->addLayout( actionsbuttons_layouts ); this->setLayout( main_layout ); this->setFixedSize( 520, 300 ); qDebug() << "Input_List MEM DIR " << &inputs_list->_list; qDebug() << "Output_List MEM DIR " << &outputs_list->_list; } void SceneContainerConfigWindow::BuildLogic() { connect( add_input, &QPushButton::clicked, this, &SceneContainerConfigWindow::AddOutput ); connect( add_output, &QPushButton::clicked, this, &SceneContainerConfigWindow::AddOutput ); qDebug() << "Input_List MEM DIR " << &inputs_list->_list; qDebug() << "Output_List MEM DIR " << &outputs_list->_list; } void SceneContainerConfigWindow::AddInput() { _input_count++; ItemDataTypeWidget* item = new ItemDataTypeWidget( ); item->SetInfo( _input_count, _options ); inputs_list->AddNewWidget( item ); } void SceneContainerConfigWindow::AddOutput() { _output_count++; outputs_list->AddNewWidget( MakeNewItem( _output_count, _options ) ); } ItemDataTypeWidget* SceneContainerConfigWindow::MakeNewItem(int pos, QStringList options) { ItemDataTypeWidget* item = new ItemDataTypeWidget(); item->SetInfo( pos, options ); return item; }
ItemDataTypeWidget.h
#ifndef ITEMDATATYPEWIDGET_H #define ITEMDATATYPEWIDGET_H #include <QWidget> #include <QLabel> #include <QListWidget> #include <QListWidgetItem> #include <QComboBox> #include <QHBoxLayout> class ItemDataTypeWidget : public QWidget { Q_OBJECT public: explicit ItemDataTypeWidget( QWidget * parent = nullptr ); void SetInfo( int input_number, QStringList types_list ); protected: void BuildWidget(); protected: QLabel* label; QComboBox* type; QHBoxLayout* layout; }; #endif // ITEMDATATYPEWIDGET_H
ItemDataTypeWidget.cpp
#include "ItemDataTypeWidget.h" ItemDataTypeWidget::ItemDataTypeWidget(QWidget* parent) : QWidget( parent ) { BuildWidget(); } void ItemDataTypeWidget::BuildWidget() { label = new QLabel( "Input", this ); type = new QComboBox( this ); layout = new QHBoxLayout(); layout->addWidget( label ); layout->addSpacing( 10 ); layout->addWidget( type ); layout->addStretch(); layout->setSizeConstraint( QLayout::SetFixedSize ); this->setLayout( layout ); } void ItemDataTypeWidget::SetInfo(int input_number, QStringList types_list) { label->setText( "Input " + QString::number(input_number) ); type->addItems( types_list ); layout->setSizeConstraint( QLayout::SetFixedSize ); }
-
Please show/take a look at the backtrace to see where it really crashes.
-
@Christian-Ehrlicher, Here is an image of the debugger. I don't know if this is exactly what you meant. From what I see in the debugger, it fails to use the QListWidget class. It seems to me that the failure comes because that pointer with the class does not exist.
The crash occurs in the AddNewWidget method of the DataTypeListWidget class.

In the following image,
I print with debug messages the memory address of the QListWidget. The curious thing is that in the third call the memory address is different. I think that there is the failure, it tries to access an invalid memory address. But I don't understand the reason, because the constructor does instantiate the class.
-
We can't see your images and you still don't tell us where exactly it crashes from your code.
-
Sorry, I didn't realize that the images are not visible. I have re-uploaded the images. I hope they are visible now.
-
@Jesus-C-Risq
How do we/you know which instance of aDataTypeListWidget
you are printing the address of_list
from? If you're going to be printing addresses I'd include&this
in your debug output. -
Your first image clearly show that the
this
pointer is a nullptr. So your pointer to DataTypeListWidget in AddNewWidget is a nullptr.
Using a debugger should be a base skill btw - I suggest you to learn such stuff, otherwise debugging and fixing problems will become a pain. -
@Christian-Ehrlicher said in Crash using QListWidget:
Your first image clearly show that the this pointer is a nullptr
Damn, you spot simple things quicker than I do :)
Same point @Jesus-C-Risq though: you need to thinking about the instances of what you're printing out. And here the instance is, well, rubbish :) -
I have already found the bug. In the end it was a silly thing, but as much as I checked the code I didn't see it.
The problem was in the SceneContainerConfigWindow class. In the BuildWidget() method these two lines were wrong:
DataTypeListWidget* inputs_list = new DataTypeListWidget( this ); DataTypeListWidget* outputs_list = new DataTypeListWidget( this );
Changing them for the following ones fixes it.
inputs_list = new DataTypeListWidget( this ); outputs_list = new DataTypeListWidget( this );
The classes were instantiated but not assigned to any pointer, that's why the "inputs_list" address was empty.
Thank you very much for the help and I take the advice to learn about debugger.