2016-06-10 43 views
0

我開發了一個帶pyside的GUI,它在按下按鈕後執行一個命令。被調用函數中的第一個命令會將text_terminal中的狀態更新爲「Downloading ...」。第二個命令將開始實際下載(通過Pandas和cx_Oracle執行的SQL查詢)。意外的執行順序 - GUI只在下載完成後更新

奇怪的是,text_terminal只會在下載完成後更新。有什麼建議可以造成這種情況?

ui.text_terminal.append("Downloading....") 
self.df = dbrs.retrieve(date) 
+1

GUI代碼通常有一個運行的事件循環來處理更新。 – stark

+0

如何確保'循環'在執行其他操作之前完成了最新的任務? – Nickpick

+0

可能發生的事情是在您下載時事件循環沒有運行。如果你想要一個GUI來做任何事情,那麼長時間運行的任務需要由一個單獨的線程來完成。 – stark

回答

2

直到重繪事件被處理,GUI纔會更新。這些通常是在事件循環開始時完成的。如果您的應用程序正忙於運行Python代碼,那麼它將不會進入事件循環的下一個循環,直到該代碼運行完畢。正確的方法是將長時間運行的操作推送到單獨的線程中,以便它不佔用主GUI線程,並且事件循環可以繼續處理GUI更新事件,但有辦法繞過它。

您可以簡單地告訴應用程序處理重繪事件。

ui.text_terminal.append("Downloading....") 
QtGui.QApplication.processEvents() 
self.df = dbrs.retrieve(date) 

調用此之前,你的retrieve功能,它應該迫使GUI的更新。

另一種方法是簡單地將操作推到下一個事件循環週期,這意味着在執行之前至少會有一次重繪。你可以用singleshot QTimer來做到這一點。這會打破你的功能流程,所以只有在下載後你沒有做其他事情的時候纔有意義。

def do_retrieve(self, date): 
    self.df = dbrs.retrieve(date) 

ui.text_terminal.append("Downloading....") 
QtCore.QTimer.singleShot(1, lambda: self.do_retrieve(date)) 
+0

下載仍然包含用戶界面,只是稍後。 「所以如果下載後你沒有做其他事情,它纔有意義。」 - 可以將「其他任何」移動到do_retrieve()中。這裏的主要問題是使用同步API進行下載,但正確的解決方案是異步啓動檢索並在完成時調用回調。 –