Pregunta

Estoy experimentando con algún código Kivy.Intenté modificar una propiedad kivy (text_colour) de una banda de rodadura creada con el roscado lib.El programa funciona bien, pero el hilo no cambia la propiedad.

También intenté crear un método en clase sobre cuál obtiene el valor como un argumento, que también falló.

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()

Salida:

[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...

¿Fue útil?

Solución

No puede modificar una propiedad Kivy o hacer cualquier trabajo relacionado con OpenGL desde un hilo externo.

La solución es programar devoluciones de llamada con el reloj de Kivy que llamará una función Desde el hilo principal de Kivy y haga el trabajo para usted.

Personalmente, cuando uso un segundo hilo, utilizo una cola para el COMER INTER-HILL de la siguiente manera:

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)

Los segundos hilos utilizan para poner las cosas en la cola. Y la devolución de llamada, cuando se llama, programe una devolución de llamada kivy usando una disparador . La función que el hilo principal de Kivy llama llame a la función OBTENIDA de la cola y establece la propiedad correspondiente.

Es útil si necesita establecer muchas propiedades. Si solo necesita establecer una sola propiedad, lo que hago es del segundo hilo, programe un callabk que utiliza parcial para hacer la parte del valor de la función. E.g:

# 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))

Otros consejos

It works for me:

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()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top