2011-07-18 19 views
3

前一段時間我寫了一個小的RAII類來包裝QApplication上的setOverrideCursor()restoreOverrideCursor()方法。構造這個類將設置遊標,並且析構函數將恢復它。由於覆蓋光標是一個堆棧,這個做得很不錯,如:Qt:從非GUI線程設置超馳光標

{ 
    CursorSentry sentry; 
    // code that takes some time to process 
} 

後來,我發現,在某些情況下,處理代碼有時會採取感知的時間來處理(比如超過半秒),而其他時間則幾乎是瞬時的(因爲緩存)。事先很難確定哪種情況會發生,因此它總是通過創建一個CursorSentry對象來設置等待光標。但是這可能會導致一個令人不快的「閃爍」,光標會從等待光標快速轉到正常光標。

所以我想我會很聰明,我添加了一個單獨的線程來管理光標覆蓋。現在,當生成CursorSentry時,它將請求遊標線程進入等待狀態。當它被銷燬時,它會告訴線程返回到正常狀態。如果CursorSentry的壽命超過一段時間(50毫秒),則處理光標更改並設置超馳光標。否則,更改請求將被丟棄。

問題是,遊標線程無法在技術上更改遊標,因爲它不是GUI線程。在大多數情況下,它確實發生了工作,但有時候,如果我真的不幸,改變遊標的調用發生在GUI線程與其他X11調用混合在一起時,並且整個應用程序被鎖定。這通常只發生在GUI線程幾乎在遊標線程決定設置覆蓋遊標的時刻完成處理。

那麼,有沒有人知道從非GUI線程設置覆蓋光標的安全方法。請記住,大多數情況下,GUI線程將忙於處理東西(這就是爲什麼需要等待遊標),所以我不能只將一個事件放入GUI線程隊列中,因爲它贏得了'直到爲時已晚。而且,將我正在討論的處理移動到單獨的線程是不切實際的,因爲這是在繪製事件期間發生的,並且在完成GUI時需要執行GUI工作(弄清楚要繪製什麼)。

任何其他增加延遲設置倍率光標的想法都是很好的。

回答

0

我不認爲除了進入GUI線程的Signal-Slot連接以及qApp->processEvents()調用之外,還有別的辦法,但正如你所說的,當GUI線程被綁定時,這可能不起作用。

QCoreApplication::processEvents的文檔還具有長的事件處理一些推薦的用法:

該功能重載processEvents()。 處理未決事件的最長時間毫秒的調用線程,或直到沒有更多 事件要處理,以較短者爲準。

當您編程忙於執行長時間操作時(例如 複製文件),您可以偶爾調用此函數 。

調用此函數僅處理調用線程的 事件。

如果可能的話,分解繪畫事件中的長時間調用,並定期檢查它看看它已經持續了多長時間。在任何這些檢查中,讓它在GUI線程中設置覆蓋光標。

通常一個QProgressBar可以很長的路向用戶傳達相同的信息。

另一個可以幫助很多的選擇是在GUI線程之外渲染到QImage緩衝區,然後在完成後將其發佈到GUI。