Altering a kivy property from another thread(从另一个线程更改 kivy 属性)
问题描述
我正在尝试一些 kivy 代码.我尝试从使用线程库创建的胎面修改 kivy 属性(text_colour
).程序运行正常,但线程没有改变属性.
I'm experimenting with some kivy code. I tried modifing a kivy property(text_colour
) from a tread created with threading lib. Program works fine but the thread does not change the property.
我还尝试在类中创建一个将值作为参数的方法,但也失败了.
I also tried to create a method in class about which gets the value as an argument, which also failed.
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...
推荐答案
您不能从外部线程修改 kivy 属性或执行任何与 OpenGL 相关的工作.
You cannot modify a kivy property or do any OpenGL related work from an external thread.
解决方案是用 kivy 的 Clock 来安排 callbacks 来调用一个函数来自 kivy 的主线程并为您完成工作.
The solution is to schedule callbacks with kivy's Clock that will call a function from kivy's main thread and do the work for you.
就个人而言,当我使用第二个线程时,我使用队列进行线程间通信,如下所示:
Personally, when I use a second thread, I use a queue for the inter-thread comm as follows:
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)
第二个线程使用 put 将东西放入队列.回调在调用时会使用 trigger.然后kivy的主线程调用的函数调用队列的get函数并设置相应的属性.
The second threads uses put to put things on the queue. And the callback, when called, schedules a kivy callback using a trigger. The function that the kivy's main thread then calls calls the get function of the queue and sets the appropriate property.
如果您需要设置许多属性,这将很有帮助.如果您只需要设置一个属性,我所做的就是从第二个线程中安排一个 callabck,它使用 partial 来使 value 成为函数的一部分.例如:
That is helpful if you need to set many properties. If you just need to set a single property, what I do is from the second thread I schedule a callabck that uses partial to make the value part of the function. 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))
这篇关于从另一个线程更改 kivy 属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从另一个线程更改 kivy 属性
基础教程推荐
- Dask.array.套用_沿_轴:由于额外的元素([1]),使用dask.array的每一行作为另一个函数的输入失败 2022-01-01
- 何时使用 os.name、sys.platform 或 platform.system? 2022-01-01
- 在 Python 中,如果我在一个“with"中返回.块,文件还会关闭吗? 2022-01-01
- Python kivy 入口点 inflateRest2 无法定位 libpng16-16.dll 2022-01-01
- 用于分类数据的跳跃记号标签 2022-01-01
- 线程时出现 msgbox 错误,GUI 块 2022-01-01
- 使用PyInstaller后在Windows中打开可执行文件时出错 2022-01-01
- 如何在海运重新绘制中自定义标题和y标签 2022-01-01
- 如何让 python 脚本监听来自另一个脚本的输入 2022-01-01
- 筛选NumPy数组 2022-01-01