Qt无法立即响应按键事件

时间:2012-06-05 09:53:51

标签: qt ubuntu block

环境: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;
    }
}

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

  • 除非你在析构函数中做了很多工作,否则破坏对象通常不是问题。销毁webview可能需要很长时间。你可能不应该像你一样摧毁它。删除的工具(请参阅下面的代码)并查看需要多长时间。

  • 您自己的代码可能正在调用阻止的API。你在打电话给任何第三方图书馆吗?你在Qt自己的API中调用任何wait...方法吗?

    如果您不确定,可以检测每个插槽和每个重新实现的虚拟方法,例如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);
    }
}