对事件循环中槽的调用排队,由Qt按向后顺序处理
Queueing calls to a slot in event loop processed in backwards order by Qt
在我正在处理的应用程序中,我有一个QLineEdit,它附加了一个标准的QObject::连接到插槽:
QObject::connect(m_searchBar, SIGNAL(textChanged(const QString &)),this,SLOT(slot_searchBar()));
如您所见,它正在将文本更改信号连接到我创作的插槽。此插槽如下所示:
void LibraryWidget::slot_searchBar()
{
QString stringToFind = m_searchBar->text();
m_searchResults->clear();
if(stringToFind.isEmpty())
{
//set stacked widget back to the library when no text in search bar
m_libraryAndSearch->setCurrentWidget(libTree);
}
else
{
//show the search results
QFont headerFont;
QTreeWidgetItem * searchingMsg = new QTreeWidgetItem;
headerFont = searchingMsg->font(0);
headerFont.setBold(false);
headerFont.setItalic(true);
searchingMsg->setText(0, "Searching...");
searchingMsg->setFont(0, headerFont);
Qt::ItemFlags currentState = searchingMsg->flags();
Qt::ItemFlags noSelect = (!(Qt::ItemIsSelectable) & currentState);
searchingMsg->setFlags(noSelect);
m_searchResults->addTopLevelItem(searchingMsg);
m_libraryAndSearch->setCurrentWidget(m_searchResults);
//m_searchThread->setTerminateAndWait();
//m_searchThread->beginThread(stringToFind);
int testTwo = 0;
for(int testInt = 0; testInt < 1000000000; testInt++)
{
testTwo++;
}
int testingThree = 0;
}
}
希望这的重要性有限,但最好向您展示以防问题的根源出在这里。
如果我在搜索栏中输入一个字符串,即有问题的QLineEdit(很快),并查看附加的调试器(Visual Studio 2010)发生了什么,那么我会看到最奇怪的事情:
如果我的搜索栏中已经有"Jake"(来自之前的搜索,输入缓慢),然后快速键入"gh",那么stringToFind
值在第一次通过插槽时是"Jakegh",然后在第二次运行时是"Jakeg"。
就好像Qt将信号发射添加到堆栈而不是队列中,然后以相反的顺序将它们服务回事件循环。
问题是:有人知道这里发生了什么吗?有没有人经历过类似的结果?
Qt 版本 4.7
代码只是为了重现问题,它不做任何事情。 int testTwo -> int testingThree 只是为了减慢代码速度。
谢谢。。。
编辑当字符串作为函数参数传入槽时,观察到相同的行为。该行
QString stringToFind = m_searchBar->text();
是试图调试和规避这种现象。
编辑二
我试图在家里重现这个。在Mac OS X 10.7上从终端构建Qt,因此没有可用的调试器。我正在使用一个非常简单的类和main.cpp其格式与上述格式相同,我无法使Qt以相反的顺序为我提供字母。不过,我可以让它错过信号。我已经将行编辑连接到文本编辑,以便每次行编辑中的文本更改时,它都会使用 QTextEdit::append(( const QString & text ))
打印到文本编辑中。
e","w",则应将"N","Ne","New"打印到文本编辑中。但是,有时它只是打印"N","新"。我有一个 for 循环,可以减慢一切速度,并且必须非常快速地按下按键。
导致这种现象第一次发生的系统必然比我构建的系统复杂得多,它在调试中运行并且运行缓慢。仍然不明白为什么这会导致这种行为,而且绝对是这样!
不要抓取文本,使用 QString 和信号。
QObject::connect(m_searchBar, SIGNAL(textChanged(const QString &)),this,SLOT(slot_searchBar(const QString &)));
然后后来
void LibraryWidget::slot_searchBar(const QString &stringToFind) {
...
至于你看到你的行为的原因,我几乎可以肯定它是Qt::QueuedConnection在某个时候。您也可以在单线程代码中使用 QueuedConnection,它只需等到下一个事件循环来执行其中的代码。查看它的详细信息:http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum。
明显的问题是你的延迟循环,据说模拟实际搜索的作用。这正是错误的处理方式。搜索应在单独的 QObject 中异步运行,然后可以移动到单独的线程。只需将搜索栏中的信号连接到搜索器对象,然后当搜索者有新结果时,它应该会发出信号。
您的测试延迟循环应该替换为类似 QTimer::singleShot(1000, this, SLOT(fakeResults()))
的东西,其中插槽中的代码调用 GUI 中的相关插槽,并带有一些虚假结果。
我建议你也把一个"观察者"对象附加到QLineEdit,以监控事物。方法如下:
// in some file, say foo.cpp
class Watcher : public QObject
{
Q_OBJECT
QPointer<QLineEdit*> const edit;
public:
Watcher(QLineEdit * ed, QObject * parent = 0) : QObject(parent), edit(ed) {
connect(ed, SIGNAL(textChanged(QString)), SLOT(monitor(QString)));
}
public slots:
void monitor(const QString & str) {
qDebug("Line edit signals text: %s", str.toLocal8Bit().constData());
if (! edit.isNull() && edit->text() != str) {
qDebug("... but line edit has text %s", edit->text().toLocal8Bit().constData());
}
}
}
#include "foo.moc" // replace 'foo' with actual name of the file (sans .cpp)
- 运行Qt时处理退出代码0xC0000135 hello world
- Qt 忙处理对话框
- QT-如何处理对话框的内存管理
- 如何在Qt中处理子类中的动态内存分配
- 为什么调用单例类 Qt 消息处理程序成员函数会出现错误:缺少参数列表
- Qt-同时处理多个数据库连接
- 在Qt中处理大数字
- 使用QT的C 处理DOM处理后的XML属性顺序
- 基于范围的 for 循环和 std::vector: 是按顺序处理的元素
- 对事件循环中槽的调用排队,由Qt按向后顺序处理
- 如果安装在单独的类上,Qt消息处理程序将崩溃
- QT批处理文件未执行
- 在Qt中处理"events"
- Qt错误处理fortran子程序
- 为什么我们在Qt中处理表单时要为ui对象声明一个命名空间?
- Qt, QSplitter.处理鼠标在拆分器下时的双击
- Qt.如何处理双击事件
- 如何在QT中处理c# COM事件
- 预先计算数据vs顺序处理
- Qt按钮处理建议