0

环境:Ubuntu,Qt Creator

在我的 Qt 应用程序中,我发现有时 Qt 不会立即响应我的按键事件,但如果我等待一段时间,它最终会响应。

我认为有些东西阻止了用户界面。

据我所知,如果 Qt 的组件(QWidget等)被破坏,Qt UI 将被阻止。我检查了我的代码,在我按下向上/向下键时没有组件被破坏。我真的很想知道是否有任何其他东西可以阻止 Qt UI。

{
    ...
    connect(webViewWidget, SIGNAL(loadfinished()), this, SLOT(addItem()));
    ...
}

void addItem()
{
    delete webViewWidget; // will this delete block UI?
    mListWidget = new ScrollWidget();
    mScrollArea = new ScrollArea(this);
    for(int i=0; i<Datalen; i++)
    {
        mListWidget->addSubItem(itemWidget);
    }
}

void keyPressEvent(QKeyEvent *event)
{
    switch(event->key)
    {
    case UP_KEY:
        scroll up;
        break;
    case DOWN_KEY:
        scroll down;
        break;
    default:
        break;
    }
}
4

2 回答 2

1

通常,在处理按键之前放入应用程序事件队列的所有其他事件之前,不会处理您的按键事件

因此,它可能是尚未完成处理的任何类型的事件。也许您可以确定是否有任何事件,例如通过使用QApplication::hasPendingEvents或通过从 QApplication 继承并在添加或完全处理事件时添加调试输出。

于 2012-06-05T12:30:22.167 回答
0
  • 对象的破坏通常不是问题,除非你在析构函数中做了很多工作。销毁 webview 可能需要很长时间。你可能不应该像你那样摧毁它。删除的仪器(参见下面的代码)并查看需要多长时间。

  • 您自己的代码可能正在调用阻塞的 API。您是否正在调用任何第三方库?wait...您是否在 Qt 自己的 API 中调用任何方法?

    如果您不确定,您可以检测每个插槽和每个重新实现的虚拟方法,例如xxxEvent(...). 您需要检测插槽和重新实现的 QObject/QWidget 方法,而不是代码中的每个方法。

  • 您可能正在产生事件风暴,可能是通过在循环中发布大量事件,或者通过发送大量连接到通过Qt::QueuedConnection. 例如,确保你没有repaint()从内部打电话paintEvent()

下面的仪器示例使用 RAII,非常易于应用。或者,您可以使用分析器。

#include <QElapsedTimer>
#define INSTRUMENT() Instrument instr__ument(__FUNCTION__)
#define INSTRUMENTLIM(lim) Instrument instr__ument(__FUNCTION__, (lim))

class Instrument {
   QElapsedTimer timer;
   int limit;
   const char * function;
public:
   Instrument(const char * name, int timeLimitMs = 20) : 
      function(name), limit(timeLimitMs) { timer.start(); }
   ~Instrument() {
      if (timer.elapsed() > limit) {
         qDebug("%s was slow, took %d ms", function, timer.elapsed());
      }
   }
}

void slot(...)
{
   INSTRUMENT();
   ...

}

void addItem()
{
    INSTRUMENT();
    delete webViewWidget; // will this delete block UI?
    mListWidget = new ScrollWidget();
    mScrollArea = new ScrollArea(this);
    for(int i=0; i<Datalen; i++)
    {
        mListWidget->addSubItem(itemWidget);
    }
}
于 2012-06-05T15:15:47.763 回答