c++11qt5qlistwidgetqstackedwidget

How to show proper QStackedWidget page after QListWidget selection


I have 1 QListWidget and 1 QStackedWidget. The QstackedWidget has three different widgets to be shown after selecting the entriesd on the QListWidget.

The problem: as I select the first choice nothing happens and nothing happens if I select the second choice, but when I select the last choice I see the widget on the QStackedWidget. This widget does not appartain to the third widget but it appartain to the first widget.

Signals of [QListWidget::currentRowChanged(C++ - QListWidget select first item) does not seem to be triggered correctly. Why is that happening? Basically seems to be triggered only the last choice instead all the others.

Below the snippet of code:

1 solution: works partially because out of three choices I can only see the last QWidget showing on the QStackedWidget:

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog)
{
    ui->setupUi(this);

    mVesPos = new VesselPosSystemWidget;
    mSonar = new SonarForm;
    mOutput = new OutputForm;
    ui->stackedWidget->addWidget(mVesPos);
    ui->stackedWidget->addWidget(mSonar);
    ui->stackedWidget->addWidget(mOutput);

    ui->horizontalLayout->addWidget(ui->stackedWidget);
    setLayout(ui->horizontalLayout);


    QObject::connect(ui->listWidget, &QListWidget::currentRowChanged,
            ui->stackedWidget, &QStackedWidget::setCurrentIndex);
}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

2 solution: works partially because out of three choices I can only see the last QWidget showing on the QStackedWidget. This solution was taken from official documentation of QStackedWidget:

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog)
{
    ui->setupUi(this);

    mVesPos = new VesselPosSystemWidget;
    mSonar = new SonarForm;
    mOutput = new OutputForm;
    ui->stackedWidget->addWidget(mVesPos);
    ui->stackedWidget->addWidget(mSonar);
    ui->stackedWidget->addWidget(mOutput);

    ui->horizontalLayout->addWidget(ui->stackedWidget);
    setLayout(ui->horizontalLayout);


    connect(ui->listWidget, QOverload<int>::of(&QListWidget::currentRowChanged),
        ui->stackedWidget, &QStackedWidget::setCurrentIndex);

}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

3 solution: same exact effect, only the third QWidget is shown:

OptionsDialog::OptionsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::OptionsDialog)
{
    ui->setupUi(this);

    mVesPos = new VesselPosSystemWidget;
    mSonar = new SonarForm;
    mOutput = new OutputForm;
    ui->stackedWidget->addWidget(mVesPos);
    ui->stackedWidget->addWidget(mSonar);
    ui->stackedWidget->addWidget(mOutput);

    ui->horizontalLayout->addWidget(ui->stackedWidget);
    setLayout(ui->horizontalLayout);


    connect(ui->listWidget, &QListWidget::currentRowChanged,
        [=](int index) { on_listWidget_currentRowChanged(index); });


}

OptionsDialog::~OptionsDialog()
{
    delete ui;
}

void OptionsDialog::on_listWidget_currentRowChanged(int currentRow)
{
    ui->stackedWidget->setCurrentIndex(currentRow);
}

I don't know what else to try to have the .ui forms switch after selcting the item in the QListWidget. Is there something I am missing? I tried all possible connect combinations but despite that I can only show the third choice.


Solution

  • I hope this could be useful for other users. I found a solution to this question. It was not easy and it required reading in depth the official documentation. Basically what was happening was that as I tried to select the proper QWidget on the QlistWidget, the selection was erroneously going to the incorrect form. I tried to

    qDebug() << ui->stackedWidget->addWidget(mSonar);
    qDebug() << ui->stackedWidget->addWidget(mOutput);
    

    And was obtaining index 3,4,5. Which explains why I was only seeing the last index. Now after long and in-depth reading of the documentation I found out about QStackedWidget::insertWidget relationships with all possible QWidget you want to link to the stack. It basically linking all the views to the form under the precise condition that what you are passing are QWidgets. So for example if you would like to link a QDialog to the QStackedWidget this is not allowed, because QStackedWidgets inherits QWidgets. Therefore the solution was to insert the correct widget right from the beginning passing the proper index manually (in my case).

    Code solution:

    OptionsDialog::OptionsDialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::OptionsDialog)
    {
        ui->setupUi(this);
        mVesPos = new VesselPosSystemWidget;
        mSonar = new SonarForm;
        mOutput = new OutputForm;
        ui->stackedWidget->insertWidget(0, mVesPos);
        ui->stackedWidget->insertWidget(1, mSonar);
        ui->stackedWidget->insertWidget(2, mOutput);
    
        // This is how to link the choice according to the latest signals notation
        connect(ui->listWidget, &QListWidget::currentRowChanged,
                ui->stackedWidget, &QStackedWidget::setCurrentIndex);
    }
    

    The function can be found here and you can actually see, if you read carefully how the inheritance works. So again int QStackedWidget::insertWidget(int index, QWidget *widget) from official documentation solved the problem. I hope this could solve the problem for other users. :)