2012-06-05 26 views
0

環境:Ubuntu的,Qt Creator的Qt可以不響應按鍵事件立即

在我的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; 
    } 
} 
+0

展示一個簡單的示例代碼,你是如何準確地看到這一點。 – rubenvb

+0

我不知道哪個代碼導致了這一點,我只是想知道阻止UI的哪個位置。據我所知,被毀壞的QWidget會導致這種情況。那還有別的嗎?謝謝。 – user1437008

+0

@rubenvb你介意我僞裝成僞碼嗎? – user1437008

回答

0
  • 對象的破壞通常不是一個問題,除非你在析構函數中做了很多工作。銷燬webview可能需要很長時間。你可能不應該像你那樣摧毀它。刪除的工具(見下面的代碼)並查看需要多長時間。

  • 您自己的代碼可能正在調用阻塞的API。你打電話給任何第三方圖書館嗎?你在調用Qt自己的API中的任何wait...方法嗎?

    如果你不確定,就可以檢測每條插槽重新實現的虛方法xxxEvent(...)。您需要儀器只有插槽和重新實現QObject/QWidget方法,而不是代碼中的每個方法。

  • 您可能正在製作一個事件風暴,可能是通過在一個循環中發佈大量事件,或者通過發送大量連接到通過Qt::QueuedConnection連接的插槽的信號。例如,確保你沒有從paintEvent()內撥打repaint()

下面的儀表示例使用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); 
    } 
} 
+0

感謝您的回覆。我有點疑惑,你說:確保你沒有從paintEvent()中調用repaint()。在我的應用程序代碼中,我發現我在painEvent()中重繪了scrollare,這是否會導致UI塊?如果是這樣,當webViewWidget發出信號時,我應該怎樣重繪滾動條:loadfinished()? – user1437008

+0

我的意思是你不應該調用'repaint()'方法。一個'paintEvent()'只能做一些事情:更新對象的內部狀態,自己做繪畫,如果你想讓你繼承的BaseClass完成一些繪畫,則調用'BaseClass :: paintEvent()'。永遠不要從'paintEvent()'調用'repaint()'。 –

1

一般來說,處理這些被按下的鍵放到應用程序的事件隊列之前的所有其他事件之前,將不會處理您的按鍵事件。

因此,它可能是任何種類的事件還沒有完成處理。也許你可以找出是否有任何事件,例如通過使用QApplication::hasPendingEvents或從QApplication繼承並在添加或完全處理事件時添加調試輸出。

+0

感謝您的回覆。我已經使用QApplication :: hasPendingEvents來檢查,實際上有事件掛起,但我仍然需要檢查它是什麼事件。我會繼續調查。 – user1437008