[Solved] NULL Model Pointer when passed through custom Widgets



  • I have a hunch as to what's causing this problem, but I don't know how QT works well enough to be sure. In an effort to modularize my program, I've taken to creating three custom widgets that I'd like to "talk" to each other using signals and slots, all encapsulated within a single widget. Here's the breakdown:

    WidgetA

    • Owns a model (verified working)
    • Has WidgetB

    WidgetB

    • Is intended to display and modify a given model
    • Has a QListView, and QPushButtons for adding/removing items from the model
    • Has a QAbstractListModel pointer called internal_model
    • Has a method setModel(QAbstractListModel* model) which sets internal_model to model, and sets the model for the QListView

    The following is observed:

    • The QAbstractListModel, model, is created in WidgetA
    • Items are added to model in WidgetA
    • WidgetB's setModel() is called
    • WidgetB's QListView displays added items properly. internal_model is set to model.
    • The QPushButton in WidgetB is pressed to insert a new row into the model (using a signal from the button, and a slot from WidgetB), interal_model is NULL.

    I feel like this is a threading problem, but I don't know if QWidgets have their own threads. This isn't a critical problem, since I can just remove WidgetB's controls and move them into WidgetA, but an answer would be helpful just to gain a deeper understanding of QT and avoid similar problems in the future. I figured one of the primary benefits of a model was that it could be passed and shared without losing consistency, but there's clearly a limitation here I don't know about.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    No there's no per-widget thread at all, widgets only live the GUI thread which is generally the main thread. Can you share the code of your widgets ? It will be easier to spot the error.

    One thing to check though: are you shadowing internal_model in WidgetB anywhere ?



  • Thanks for the kindly welcome and the reply! The NULL problem throws when calling InsertLayer due to the pressing of the "+" push button. Here's the code for each part of the program:

    MainWindow.cpp

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        model = new LayersModel(this);
        qDebug() << "LayersModel created in MainWindow";
        model->insertLayer(0, LayerType::Tile, "Test");
    
        LayersWidget* widget = new LayersWidget(this);
        widget->setModel(model);
        setCentralWidget(widget);
    }
    

    LayersWidget

    class LayersWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit LayersWidget(QWidget *parent = 0);
        void setModel(LayersModel* model);
    
    signals:
    
    public slots:
    
    private:
        //UI Elements
        QListView* ui_lsvLayers;
        QPushButton* ui_btnAdd;
        QPushButton* ui_btnRemove;
    
        //Models
        LayersModel* mdl_layers;
    
    private slots:
        void insertLayer();
        void removeLayer();
    };
    
    LayersWidget::LayersWidget(QWidget *parent) :
        QWidget(parent)
    {
        qDebug() << "New LayersWidget created.";
        mdl_layers = NULL;
    
        ui_lsvLayers = new QListView(this);
    
        ui_btnAdd = new QPushButton("+");
        ui_btnAdd->setEnabled(false);
        connect(ui_btnAdd, SIGNAL(clicked()), this, SLOT(insertLayer()));
    
        ui_btnRemove = new QPushButton("-");
        ui_btnRemove->setEnabled(false);
        connect(ui_btnRemove, SIGNAL(clicked()), this, SLOT(removeLayer()));
    
        QHBoxLayout* buttonBar = new QHBoxLayout;
        buttonBar->addWidget(ui_btnAdd);
        buttonBar->addWidget(ui_btnRemove);
    
        QVBoxLayout* mainLayout = new QVBoxLayout;
        mainLayout->addWidget(ui_lsvLayers);
        mainLayout->addLayout(buttonBar);
    
        setLayout(mainLayout);
    }
    
    void LayersWidget::insertLayer()
    {
        if(mdl_layers != NULL)
        {
            NewLayerDialog layerDlg(this);
            if(layerDlg.exec() == QDialog::Accepted)
            {
                if(ui_lsvLayers->currentIndex() == QModelIndex())
                {
                    mdl_layers->insertLayer(0, layerDlg.getType(), layerDlg.getName());
                }
                else
                {
    
                }
            }
        }
    }
    
    void LayersWidget::removeLayer()
    {
    
    }
    
    void LayersWidget::setModel(LayersModel *model)
    {
        qDebug() << "Model assigned";
        ui_lsvLayers->setModel(model);
        ui_btnAdd->setEnabled(true);
        ui_btnRemove->setEnabled(true);
    }
    


  • Now I feel foolish...I can't believe I forgot to store the pointer in setModel. No wonder it's invalid.


  • Lifetime Qt Champion

    Don't worry, it's something everybody did at one point or another.

    Since you have found the problem, please update the thread title prepending [solved] so other forum users may know a solution has been found :)



  • Thanks for the advice. I saw other posts marked the same way, but wasn't sure how to do so.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.