2014-02-26 3 views
5

일부 kivy 코드로 실험 중입니다. 스레드 lib로 만든 트레드에서 kivy 속성 (text_colour)을 수정 해 보았습니다. 프로그램이 제대로 작동하지만 스레드가 속성을 변경하지 않습니다.다른 스레드에서 kivy 속성 변경하기

클래스에 대해서도 값을 인수로 가져 오는 메소드를 만들려고했는데 실패했습니다.

from kivy.app import App 

from kivy.uix.boxlayout import BoxLayout 
from kivy.properties import ListProperty 


import threading 
import random 
import time 


def zaaa(): 
    import time 
    time.sleep(3) 
    ScatterTextWidget.text_colour = [0, 0, 1, 1] 
    print "function ran" 

t = threading.Thread(target= zaaa) 
t.start() 


class ScatterTextWidget(BoxLayout): 

    text_colour = ListProperty([1, 0, 0, 1]) 

    def change_label_colour(self, *args): 
     colour = [random.random() for i in xrange(3)] + [1] 
     self.text_colour = colour 

    def press(self, *args): 
     self.text_colour = [1, 1, 1, 1] 


class TataApp(App): 
    def build(self): 
     return ScatterTextWidget() 


if __name__ == "__main__": 
    TataApp().run() 

출력 :

[INFO    ] Kivy v1.8.0 
[INFO    ] [Logger  ] Record log in /home/mbp/.kivy/logs/kivy_14-02-26_44.txt 
[INFO    ] [Factory  ] 157 symbols loaded 
[DEBUG    ] [Cache  ] register <kv.lang> with limit=None, timeout=Nones 
[DEBUG    ] [Cache  ] register <kv.image> with limit=None, timeout=60s 
[DEBUG    ] [Cache  ] register <kv.atlas> with limit=None, timeout=Nones 
[INFO    ] [Image  ] Providers: img_tex, img_dds, img_pygame, img_pil, img_gif 
[DEBUG    ] [Cache  ] register <kv.texture> with limit=1000, timeout=60s 
[DEBUG    ] [Cache  ] register <kv.shader> with limit=1000, timeout=3600s 
[DEBUG    ] [App   ] Loading kv </home/mbp/workspace/KiviPlay/tata.kv> 
[DEBUG    ] [Window  ] Ignored <egl_rpi> (import error) 
[INFO    ] [Window  ] Provider: pygame(['window_egl_rpi'] ignored) 
libpng warning: iCCP: known incorrect sRGB profile 
[DEBUG    ] [Window  ] Display driver x11 
[DEBUG    ] [Window  ] Actual window size: 800x600 
[DEBUG    ] [Window  ] Actual color bits r8 g8 b8 a8 
[DEBUG    ] [Window  ] Actual depth bits: 24 
[DEBUG    ] [Window  ] Actual stencil bits: 8 
[DEBUG    ] [Window  ] Actual multisampling samples: 2 
[INFO    ] [GL   ] OpenGL version <4.3.12618 Compatibility Profile Context 13.251> 
[INFO    ] [GL   ] OpenGL vendor <ATI Technologies Inc.> 
[INFO    ] [GL   ] OpenGL renderer <AMD Radeon HD 7700 Series> 
[INFO    ] [GL   ] OpenGL parsed version: 4, 3 
[INFO    ] [GL   ] Shading version <4.30> 
[INFO    ] [GL   ] Texture max size <16384> 
[INFO    ] [GL   ] Texture max units <32> 
[DEBUG    ] [Shader  ] Fragment compiled successfully 
[DEBUG    ] [Shader  ] Vertex compiled successfully 
[DEBUG    ] [ImagePygame ] Load </usr/lib/python2.7/site-packages/Kivy-1.8.0-py2.7-linux-x86_64.egg/kivy/data/glsl/default.png> 
[INFO    ] [Window  ] virtual keyboard not allowed, single mode, not docked 
[INFO    ] [Text  ] Provider: pygame 
[DEBUG    ] [Cache  ] register <kv.loader> with limit=500, timeout=60s 
[INFO    ] [Loader  ] using a thread pool of 2 workers 
[DEBUG    ] [Cache  ] register <textinput.label> with limit=None, timeout=60.0s 
[DEBUG    ] [Cache  ] register <textinput.width> with limit=None, timeout=60.0s 
[DEBUG    ] [Atlas  ] Load </usr/lib/python2.7/site-packages/Kivy-1.8.0-py2.7-linux-x86_64.egg/kivy/data/../data/images/defaulttheme.atlas> 
[DEBUG    ] [Atlas  ] Need to load 1 images 
[DEBUG    ] [Atlas  ] Load </usr/lib/python2.7/site-packages/Kivy-1.8.0-py2.7-linux-x86_64.egg/kivy/data/../data/images/defaulttheme-0.png> 
[DEBUG    ] [ImagePygame ] Load </usr/lib/python2.7/site-packages/Kivy-1.8.0-py2.7-linux-x86_64.egg/kivy/data/../data/images/defaulttheme-0.png> 
[INFO    ] [GL   ] NPOT texture support is available 
[INFO    ] [OSC   ] using <multiprocessing> for socket 
[DEBUG    ] [Base  ] Create provider from mouse 
[DEBUG    ] [Base  ] Create provider from probesysfs 
[DEBUG    ] [ProbeSysfs ] using probsysfs! 
[INFO    ] [Base  ] Start application main loop 
<kivy.properties.ListProperty object at 0x124f870> 
function ran 
[INFO    ] [Base  ] Leaving application in progress... 

답변

4

당신은 kivy 속성을 수정하거나 외부 스레드에서 OpenGL을에게 관련 작업을 할 수 없습니다.

해결책은 kivy 's Clock의 기능을 호출하는 kivy 's Clock으로 callbacks을 예약하고 작업을 수행하는 것입니다.

from Queue import Queue 

class KivyQueue(Queue): 
    ''' 
    A Multithread safe class that calls a callback whenever an item is added 
    to the queue. Instead of having to poll or wait, you could wait to get 
    notified of additions. 

    >>> def callabck(): 
    ...  print('Added') 
    >>> q = KivyQueue(notify_func=callabck) 
    >>> q.put('test', 55) 
    Added 
    >>> q.get() 
    ('test', 55) 

    :param notify_func: The function to call when adding to the queue 
    ''' 

    notify_func = None 

    def __init__(self, notify_func, **kwargs): 
     Queue.__init__(self, **kwargs) 
     self.notify_func = notify_func 

    def put(self, key, val): 
     ''' 
     Adds a (key, value) tuple to the queue and calls the callback function. 
     ''' 
     Queue.put(self, (key, val), False) 
     self.notify_func() 

    def get(self): 
     ''' 
     Returns the next items in the queue, if non-empty, otherwise a 
     :py:attr:`Queue.Empty` exception is raised. 
     ''' 
     return Queue.get(self, False) 

번째 스레드가 큐에 물건을 넣어 넣어 사용 I 번째 스레드를 사용하면 다음과

개인적, I는 스레드 간 통신을 위해 큐를 사용한다. 호출 될 때 콜백은 trigger을 사용하여 kivy 콜백을 예약합니다. kivy의 메인 스레드가 호출하는 함수는 큐의 get 함수를 호출하고 적절한 속성을 설정합니다.

많은 속성을 설정해야하는 경우 유용합니다. 하나의 속성 만 설정해야하는 경우 두 번째 스레드에서 callabck을 예약하여 partial을 사용하여 함수의 값 부분을 만듭니다. 예컨대는 :

# this may only be called from the main kivy thread 
def set_property(value, *largs): 
    self.kivy_property = value 

# the second thread does this when it wants to set self.kivy_property to 10 
Clock.schedule_once(partial(set_property, 10)) 
1

그것은 나를 위해 작동 :

from kivy.app import App 
from kivy.uix.label import Label 
import threading 

import time 

class ScatterTextWidget(Label): 

    def __init__(self,**kwargs): 
    self.text = 'nima' 
    self.color = [0, 1, 1, 1] 
    super(ScatterTextWidget, self).__init__(**kwargs) 
a = ScatterTextWidget() 
def zaaa(): 
    import time 
    time.sleep(3) 
    a.color = [0, 0, 1, 1] 
    print "function ran" 

t = threading.Thread(target= zaaa) 
t.start() 

class TataApp(App): 
    def build(self): 
     return a 


if __name__ == "__main__": 
    TataApp().run()