1

在我正在处理的应用程序中,我有一个 QLineEdit,它附有一个标准 QObject::connect 到一个插槽:

QObject::connect(m_searchBar, SIGNAL(textChanged(const QString &)),this,SLOT(slot_searchBar()));

如您所见,它将 textChanged 信号连接到我创建的插槽。此插槽如下所示:

   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 )).

例如,如果我键入“N”、“e”、“w”,则应将“N”、“Ne”、“New”打印到文本编辑中。但是,有时它只是打印“N”、“New”。我有一个 for 循环减慢一切,并且必须非常快地击键。

第一次导致这种现象发生的系统必然比我构建的系统复杂得多,它在调试中运行并且运行缓慢。仍然不明白为什么这会导致这种行为,而且它肯定是这样的!

4

2 回答 2

0

明显的问题是您的延迟循环,据说模拟了实际搜索的作用。这正是处理它的错误方法。搜索应该在一个单独的 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)
于 2012-06-11T20:10:20.190 回答
0

不要抓取文本,在信号中使用 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

于 2012-06-11T20:13:14.463 回答