2014-10-10 127 views
4

我有一個Python腳本,對用戶文件執行一些密集處理,可能需要一些時間。我使用Kivy爲它建立了一個用戶界面,它允許用戶選擇文件,處理模式,並在過程繼續時向他們顯示一些消息。Python Kivy:正確啓動更新GUI元素的後臺進程

我的問題是,當主Kivy循環傳遞調用底層用戶界面時,窗口凍結。

從我所瞭解的情況來看,解決此問題的正確方法是創建一個單獨的進程,腳本將從其卸載並從中將其發送到用戶界面。

但是,我無法找到如何執行此操作或關於如何將消息從單獨的線程發送迴應用程序的任何規範的示例。

有人請舉例說明如何正確地做到這一點,或指向我的文檔有關的主題?

更新:

爲了保持節目可維護性的緣故,我想避免從主線程中調用處理器的迴路的元素,而是調用回來的更新的元素一個漫長的過程GUI,例如進度條或文本字段。看起來這些元素只能從主Kivy線程修改。我如何從外部訪問它們?

回答

4

使用發佈者/消費者模型here。下面是該鏈接修改爲使用獨立的線程的例子:

from kivy.app import App 
from kivy.clock import Clock, _default_time as time # ok, no better way to use the same clock as kivy, hmm 
from kivy.lang import Builder 
from kivy.factory import Factory 
from kivy.uix.button import Button 
from kivy.properties import ListProperty 

from threading import Thread 
from time import sleep 

MAX_TIME = 1/60. 

kv = ''' 
BoxLayout: 
    ScrollView: 
     GridLayout: 
      cols: 1 
      id: target 
      size_hint: 1, None 
      height: self.minimum_height 

    MyButton: 
     text: 'run' 

<[email protected]>: 
    size_hint_y: None 
    height: self.texture_size[1] 
''' 

class MyButton(Button): 
    def on_press(self, *args): 
     Thread(target=self.worker).start() 

    def worker(self): 
     sleep(5) # blocking operation 
     App.get_running_app().consommables.append("done") 

class PubConApp(App): 
    consommables = ListProperty([]) 

    def build(self): 
     Clock.schedule_interval(self.consume, 0) 
     return Builder.load_string(kv) 

    def consume(self, *args): 
     while self.consommables and time() < (Clock.get_time() + MAX_TIME): 
      item = self.consommables.pop(0) # i want the first one 
      label = Factory.MyLabel(text=item) 
      self.root.ids.target.add_widget(label) 

if __name__ == '__main__': 
    PubConApp().run() 
+0

這是一個很好的例子,我讀過他們的文檔。問題是我必須將主要應用程序中的底層腳本的調用分段。這是我特別想避免的。我有一個觀察者監視消息並將它們發送回GUI,但它不添加元素GUI,它只是修改元素的屬性,例如高級欄值或文本字段文本。看來在這種情況下,來自線程的信號無法返回到主線程。我如何繞過這個? – chiffa 2014-10-10 20:07:24

+0

您可以嘗試使用['kivy.clock.mainthread'裝飾器](http://kivy.org/docs/api-kivy.clock.html#kivy.clock.mainthread)在主線程中調度回調的調用。 。一些例子:https://github.com/kivy/kivy/wiki/Working-with-Python-threads-inside-a-Kivy-application – Nykakin 2014-10-10 20:48:58

1

要注意:雖然從另一個線程修改kivy財產名義上的作品,有種種跡象表明,這不是一個線程安全的操作。 (使用調試器並逐步執行後臺線程中的追加功能。)Altering a kivy property from another thread指出您不應以這種方式修改屬性。