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槽,分别接受按钮按下信号,和列表选择项变化信号
#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);
最后解决...