1

Sorry for the bulky title.

I have a class containing a QListWidget. I connected it's itemSelectionChanged() signal to a custom slot.

When I call QListWidget::clear(), the slot gets called (as expected) but a call to QListWidget::count() in this slot returns the number of items the QListWidget had before.

A call to count() right after the call to clear() (when the signal was processed as described) returns the correct number 0.

I prepared a complete demo project. Most important is this source file:

#include "ListWidgetTest.hpp"
#include "ui_ListWidgetTest.h"
#include <QDebug>

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

    for (int i = 0; i < 5; ++i) {
        QListWidgetItem* item = new QListWidgetItem(QString("Item %1").arg(i));
        ui->listWidget->addItem(item);
    }

    QObject::connect(ui->pushButton, SIGNAL(clicked()),
                     this, SLOT(clearList()));

    QObject::connect(ui->listWidget, SIGNAL(itemSelectionChanged()),
                     this, SLOT(selectionChanged()));
}

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

void ListWidgetTest::clearList()
{
    qDebug() << "void ListWidgetTest::clearList()";
    ui->listWidget->clear();
    qDebug() << "clearList: ui->listWidget->count() is " << ui->listWidget->count();
}

void ListWidgetTest::selectionChanged()
{
    qDebug() << "void ListWidgetTest::selectionChanged()";
    qDebug() << "selectionChanged: ui->listWidget->count() is " << ui->listWidget->count();
}

Output

void ListWidgetTest::clearList() 
void ListWidgetTest::selectionChanged() 
selectionChanged: ui->listWidget->count() is  5
clearList: ui->listWidget->count() is  0

What happens

  1. The list gets populated.
  2. Every click on an item calls selectionChanged()
  3. A click on the button calls clearList()
  4. The call to QListWidget::clear() also emits the signal and the slot gets called
  5. The number of items has not changed yet
Morwenn
  • 21,684
  • 12
  • 93
  • 152
HWende
  • 1,705
  • 4
  • 18
  • 30

2 Answers2

1

You can add "Qt::QueuedConnection" to both of QObject::connection. Like:

connect(ui->pushButton, SIGNAL(clicked()),
                 this, SLOT(clearList()), Qt::QueuedConnection);

connect(ui->listWidget, SIGNAL(itemSelectionChanged()),
                 this, SLOT(selectionChanged()), Qt::QueuedConnection);

It is works. But sorry I don't know why. Maybe queued connection method can solve multi-signal order problem.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
ytexas
  • 11
  • 2
  • Some explanation can be found [here](https://stackoverflow.com/questions/15051553/qt-signals-queuedconnection-and-directconnection) – Peter Jul 08 '21 at 10:33
0

First of all QListWidget::clear() is a SLOT and not a SIGNAL. So obviously it is not emitting/triggering the signal itemSelectionChanged().

You might be accidentally triggering this itemSelectionChanged() just before calling clear(). Check whether you are triggering itemchanged() or selectionchanged() or any other events that trigger itemSelectionChanged() before calling clear().

 One possible solution is to declare a custom signal and emit this signal just 
 after calling clear(). And connect it to the custom slot you have defined.You
 will get the expected value in your SLOT
ScarCode
  • 3,074
  • 3
  • 19
  • 32
  • The SIGNAL itemSelectionChanged() IS emitted by calling the SLOT clear(). Since clear removes all items, the selection changes and thus the signal is emitted. Your solution is nevertheless possible but does not explain the problem. – HWende May 21 '12 at 10:56
  • What I did is on a button click I called clear. And in the SLOT(corresponding to itemselectionchanged()) I put the code to display the count in a lineedit.But nothing got displayed. So what should I infer from this, eh? Please put some of your code here. – ScarCode May 21 '12 at 11:20
  • Created a demo project and linked it. – HWende May 21 '12 at 11:58
  • executed it and output in my system was..... void ListWidgetTest::clearList() clearList: ui->listWidget->count() is 0. And no messages from Selectionchanged(). – ScarCode May 21 '12 at 12:07
  • And when I called Selectionchanged() in clearlist() after clear(), output was..void ListWidgetTest::clearList() clearList: ui->listWidget->count() is 0 void ListWidgetTest::selectionChanged() selectionChanged: ui->listWidget->count() is 0 – ScarCode May 21 '12 at 12:10
  • When I immediately click on clear (button) I get the same result as you. But when I first select an item and then click the button I definitely get the signal emitted... I add output to my post. – HWende May 21 '12 at 12:13
  • Yeah, now me too got the same.electionChanged: ui->listWidget->count() is 5 void ListWidgetTest::clearList() void ListWidgetTest::selectionChanged() selectionChanged: ui->listWidget->count() is 5 clearList: ui->listWidget->count() is 0 – ScarCode May 21 '12 at 12:17
  • As I told you, since this clear is a SLOT, it does not restrict any other signals to have emitted in the meantime. Means other signal may get triggered even before completion of clear(). This happens because as some item is selected and when we call clear(). first thing that happens is, the selected row get deselected(thus triggering itemselectionchanged() and still the count value is 5 for the triggered signal as the clear process is yet to finish).Thus it prints 5. – ScarCode May 21 '12 at 12:24