Qt 的信号顺序问题(以QListWidget 的itemSelectionChanged为例)

Qt 多信号顺序问题:

5.4在Qt的xchat频道看到的提问:

xVim:

Hi. I have a QTableWidget and delete a selected row from it. Therefore, the itemSelectionChanged signal is triggered, which is connected to my slot s. Why does QTableWidget.rowCount() inside that custom slot s give the wrong number of table entries (the number before the deletion)?

Someone else on stackoverflow has the same (unresolved) problem with a QListWidget: https://stackoverflow.com/q/10682621

I am not sure whether I should file a bug for the wrong result of the rowCount() call - I somehow doubt that it is a bug. But I cannot explain why it gives the wrong value in my code. And other people seem to get the same wrong result.


大意是xVim为QTableWidget的itemSelectionChanged连接了一个自定义的槽,结果清空表格时 与itemSelectionChanged连接的槽调用rowCount()得到的却是清空前的行数。而StackOverflow 中这位 https://stackoverflow.com/q/10682621 也遇到同样问题。

模拟之:

ListWidgetTest.ui:一个带两个默认名称pushButton(QPushButton类)和listWidget(QListWidget) 的Widget

ListWidgetTest.h

#ifndef LISTWIDGETTEST_H
#define LISTWIDGETTEST_H

#include 

namespace Ui {
class ListWidgetTest;
}

class ListWidgetTest : public QWidget
{
    Q_OBJECT
public slots:
    void clearList();
    void selectionChanged();

public:
    explicit ListWidgetTest(QWidget *parent = 0);
    ~ListWidgetTest();

private:
    Ui::ListWidgetTest *ui;
};

#endif // LISTWIDGETTEST_H

一个列表类,含有clearList,和selectionChanged槽,分别接受按钮按下信号,和列表选择项变化信号


ListWidgetTest.cpp

#include "ListWidgetTest.h"
#include "ui_ListWidgetTest.h"
#include 

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

clearList,和selectionChanged槽,分别接受按钮按下信号并清空列表,和列表选择项变化信号


Main.cpp:

....

    ListTestWidget list;

    list.show();

....

执行结果(鼠标选中任意项,再点击按钮,清空列表):

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

clear清空操作应该先触发,而itemChanged时列表应该完成清空,但可见结果并不是,而是清空之前的行数。

个人(无根据)推测:Qt信号的冲突问题,清空操作并不能瞬间完成(逐项),但列表项已经发生变化,信号已经发出,故得到错误的rowCount()。(此处得多加探索...)

解决办法:在QObject::connection加上第五个参数Qt::QueuedConnection

// ListWidgetTest.cpp:
 
    QObject::connect(ui->pushButton, SIGNAL(clicked()),
                     this, SLOT(clearList()), Qt::QueuedConnection);

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

最后解决...

你可能感兴趣的:(Qt)