Сигнал itemSelectionChanged() QListWidget при вызове clear()

Извините за громоздкий заголовок.

У меня есть класс, содержащий QListWidget. Я подключил его сигнал itemSelectionChanged() к пользовательскому слоту.

Когда я вызываю QListWidget::clear(), слот вызывается (как и ожидалось), но вызов QListWidget::count() в этом слоте возвращает количество элементов, которые QListWidget имел раньше.

Вызов count() сразу после вызова clear() (когда сигнал был обработан, как описано) возвращает правильное число 0.

Я подготовил полный демонстрационный проект. Наиболее важным является этот исходный файл:

#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();
}

Вывод

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

Что происходит

  1. Список заполняется.
  2. Каждый щелчок по элементу вызывает selectionChanged()
  3. Щелчок по кнопке вызывает clearList()
  4. Вызов QListWidget::clear() также генерирует сигнал, и слот вызывается
  5. Количество элементов пока не изменилось

person HWende    schedule 21.05.2012    source источник


Ответы (2)


Вы можете добавить «Qt::QueuedConnection» к обоим из QObject::connection. Нравиться:

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

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

Это работает. Но извините, я не знаю, почему. Возможно, метод соединения с очередью может решить проблему порядка нескольких сигналов.

person ytexas    schedule 05.05.2018
comment
Некоторые пояснения можно найти здесь - person Peter; 08.07.2021

Во-первых, QListWidget::clear() — это SLOT, а не SIGNAL. Таким образом, очевидно, что он не излучает/запускает сигнал itemSelectionChanged().

Возможно, вы случайно активировали этот itemSelectionChanged() непосредственно перед вызовом clear(). Перед вызовом clear() проверьте, инициируете ли вы itemchanged() или selectionchanged() или любые другие события, которые запускают itemSelectionChanged().

 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
person ScarCode    schedule 21.05.2012
comment
СИГНАЛ itemSelectionChanged() выдается вызовом SLOT clear(). Поскольку при очистке удаляются все элементы, выбор изменяется и, таким образом, выдается сигнал. Ваше решение, тем не менее, возможно, но не объясняет проблему. - person HWende; 21.05.2012
comment
То, что я сделал, это нажатие кнопки, которое я назвал очисткой. И в SLOT (соответствующий itemselectionchanged()) я поместил код для отображения количества в строке. Но ничего не отобразилось. Так что я должен заключить из этого, а? Пожалуйста, поместите часть вашего кода здесь. - person ScarCode; 21.05.2012
comment
Создал демонстрационный проект и связал его. - person HWende; 21.05.2012
comment
выполнил его, и вывод в моей системе был..... void ListWidgetTest::clearList() clearList: ui-›listWidget-›count() равен 0. И никаких сообщений от Selectionchanged(). - person ScarCode; 21.05.2012
comment
И когда я вызвал Selectionchanged() в clearlist() после clear(), вывод был..void ListWidgetTest::clearList() clearList: ui->listWidget->count() is 0 void ListWidgetTest::selectionChanged() selectionChanged: ui -›listWidget-›count() равно 0 - person ScarCode; 21.05.2012
comment
Когда я сразу нажимаю очистить (кнопку), я получаю тот же результат, что и вы. Но когда я сначала выбираю элемент, а затем нажимаю кнопку, я определенно получаю излучаемый сигнал... Я добавляю вывод в свой пост. - person HWende; 21.05.2012
comment
Да, теперь у меня тоже самое. : ui-›listWidget-›count() равно 0 - person ScarCode; 21.05.2012
comment
Как я уже говорил, поскольку этот клир является SLOT, он не ограничивает появление каких-либо других сигналов в это время. Означает, что другой сигнал может сработать даже до завершения очистки(). Это происходит потому, что когда какой-то элемент выбран и когда мы вызываем clear(). первое, что происходит, это то, что выбранная строка становится невыбранной (таким образом, вызывается itemselectionchanged(), и значение счетчика по-прежнему равно 5 для сработавшего сигнала, поскольку процесс очистки еще не завершен). Таким образом, он печатает 5. - person ScarCode; 21.05.2012