2016-07-24 56 views
-1

我有一個使用python 2.7.10中的Tkinter構建的GUI程序。TkInter;被告知更新無響應

它的工作完美無瑕,因爲它的根本原因。

不幸的是,它在進行交互時會暫時進入Windows可怕的「無響應」狀態。

以下是佈局總結:

啓動腳本啓動主腳本。主腳本讀取設置文件並啓動GUI腳本。 GUI腳本啓動GUI。 用戶輸入一個術語來搜索一系列文件。 GUI腳本進入側面腳本來處理文件並檢索結果。 側面腳本繼承GUI腳本的某些方面。 使用繼承元素工作時,側腳本嘗試更新用戶; GUI沒有它。 在返回到GUI腳本並顯示結果之前,GUI暫時無響應。

以下是我需要它去簡稱:

啓動腳本啓動主腳本。主腳本讀取設置文件並啓動GUI腳本。 GUI腳本啓動GUI。 用戶輸入一個術語來搜索一系列文件。 GUI腳本進入側面腳本來處理文件並檢索結果。 側面腳本繼承GUI腳本的某些方面。 側邊腳本使用GUI元素在工作時用進度條和圖像更新用戶。 GUI返回到GUI腳本並顯示結果。

我已經建立了進度條,但圖像還沒有,但如果進度條不起作用,我不會浪費我的時間在圖像上。

樣本不可能,不被使用但顯示點代碼; GUI;

import Tkinter, PIL, SideScript1 

Tkinter() 

ShowText() 
ShowStuff() 
input = GetInput() 
ShowProgressBar() 
SideScript1.processfilesbasedoninput(input, progressbarcontrolvar) 
DisplayResults() 

SideScript1

def proccessfilesbasedoninput(input, pbcv): 
    DoStuff() 
    pbcv.gofurther(5) 
    DoMoreStuff() 
    pbcv.goevenfurther(10) 
    a1sauce = RandomMathsStuffs() 
    for all the data in every file in that one directory: 
     ReadData() 
     pbcv.goabitfurther(a1sauce) 
     if data is what I want: 
      break 
    pbcv.step(-100) 
    return data 

我想我的問題是,我該如何獲得GUI來更新這些元素,而不是去無意識?

我們正在談論100個000文件和1.5秒它在做

更新:這個問題已經被標記爲與其他副本。是嗎?是的。但那是因爲我((並且仍然))不確定如何搜索這種問題,並且那裏的三個解決方案; multithreading,multiprocessing和更小的任務。不幸的是,該程序是建立在單線程和進程上運行的,如果沒有完全重寫,獲得預期的GUI響應會導致巨大的減速,如果它工作的話。

我確實看到了問題,因爲TKinter是一個阻塞模塊。不幸的是,我非常清楚如何在不造成大量錯誤或完全重寫的情況下解除它。

+1

[在Tkinter中執行函數時程序凍結]的可能重複(http://stackoverflow.com/questions/10847626/program-freezing-during-the-execution-of-a-function-in-tkinter ) –

+0

對不起,我不確定如何搜索這樣的問題。 不幸的是,該程序是基於單線程的,不能在多個進程上運行,並且不能在沒有完全重寫的情況下分解爲塊。 有沒有其他可能的解決方案或類似的線程? –

+0

無法使用多線程工作,您只需在新線程中運行'.mainloop()'。 (那麼,你必須重寫那些修改小部件的代碼部分,因爲只有主循環線程應該與Tkinter進行交互。)如果__really__不能這樣做,那麼你唯一的選擇是定期調用'update_idletasks'同時執行其他任務。 –

回答

0

鏈接的重複問題有答案。不好的一個 - 但答案不會少。

update_idletasks

我試過了,它工作!好。有點。

它起初工作,然後同樣的結果來了。 GUI暫時凍結。

然後一個想法突然出現在我的腦海裏。爲什麼不嘗試update呢?

我這麼做了,它按照我的需要工作,但是它有很大的性能損失 - 幾乎與update_idletasks相同。

爲了解決這個新問題,我添加了一些更多的數學來引起更新,在我的情況下,每300個文件,而不是每個文件 - 平衡性能打擊和用戶不立即刪除我的程序,因爲是,它會對您的資源造成損失。不,我最初並沒有聽從這個建議。先拍,稍後再提問,對嗎?

我是如何使用它的?很高興我問過!這是一個例子。

#GUI Code 
DoStuff() 
SideScript1.proccessdata(arg, kwarg, debate) 
DoMoreStuff() 

#File Management Code 
DoStuff() 
filenumber = 0 
maxfilenumber = 0 
for every file I need to search: 
    SearchFile() 
    filenumber +=1 
    if filenumber == maxfilenumber: 
     tkinter.update() #in my case, it was tkinst, or "TkInter Instance", since it was inherited from the GUI attributes. 
     filenumber = 0 
    if data is what I want: 
     break 
return data 

我不知道所有的後端和鐵的事實,但update()似乎多了很多用戶超過update_idletasks()友好,更快,少了很多容易出錯和怠工也是如此。

我的詭計現在恢復正常,平穩高效地以每秒60((30?120?250??? ??))的幀速度運行 - 並且Tk在每次請求時都沒有靜坐罷工它的信息了!

謝謝@Rawing試圖幫助!

+1

沒有什麼魔力:'update'本質上是一次全程通過'mainloop'(或者更準確地說,一個新的臨時'mainloop'),而'update_idletasks'只處理待處理的「空閒」事件。換句話說,'update_idletasks'完成'update'工作的一個子集。 –

+0

我完全相信 - 但是對我的視力不佳,似乎'.update()'更快。我確實看到這會導致問題使用'.update_idletasks()'保持不固定。我知道我正在運行一臺功能非常強大的個人電腦,但是,還有其他什麼能讓'update'看起來比'update_idletasks'更快,即使它實際上在做更多的工作,或者我只是在想什麼? –

+0

用另一個'loop'暫停'mainloop'?如何在沒有'thread'的情況下分割一個gui app? – dsgdfg