[英]Threading Problem Kivy image texture not updating when threading is used
I am trying to make a application using Kivy that use threading.我正在尝试使用使用线程的 Kivy 制作应用程序。 The background thread updates the texture in the Image Widget main class.后台线程更新 Image Widget 主 class 中的纹理。
The problem is that the texture variable gets updated but is not displayed in the kivy Gui app问题是纹理变量已更新但未显示在 kivy Gui 应用程序中
The here's the code I have used ObjectProperty to trigger update both label:text and the Image:Texture But only the Label:text gets really updated这是我使用ObjectProperty触发更新label:text和Image:Texture但只有Label:text得到真正更新的代码
import random
import threading
from kivy.app import App
from kivy.core.image import Texture
from kivy.lang import Builder
from kivy.properties import NumericProperty, ObjectProperty
from kivy.uix.widget import Widget
Builder.load_string('''
<Main>:
btn1:btn1
label1:label1
img1:img1
GridLayout:
cols:1
size:root.width,root.height
Button:
text:"Hello"
id:btn1
on_release:root.btn()
Label:
id:label1
text:"hello"
Image:
id:img1
''')
class Main(Widget):
btn1 = ObjectProperty(None)
label1 = ObjectProperty(None)
img1 = ObjectProperty(None)
a = ObjectProperty(1)
newtexture = ObjectProperty(2)
update = False
iter = 1
def btn(self):
self.update = not self.update
t1 = threading.Thread(target=self.updateValue)
t1.start()
# self.updateValue()
def updateValue(self):
while (self.update):
self.a += 2
testexture = Texture.create(size=(512, 512), colorfmt='rgb')
size = 512 * 512 * 3
if self.iter == 1:
buf = [int(x % 128) for x in range(size)]
self.iter = 0
# print("strip")
else:
buf = [int(x % 256) for x in range(size)]
self.iter = 1
# print("random")
buf = bytearray(buf)
testexture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
self.newtexture = testexture
# print("Generated")
def on_a(self, instance, value):
print('My property a changed to', value)
self.label1.text = str(value)
def on_newtexture(self, instance, value):
self.img1.texture = value
self.img1.canvas.ask_update()
print("updated texture")
print(value)
class MaainApp(App):
def build(self):
return Main()
MaainApp().run()
Another thing if you Remove the While loop in update And Threading, and just trigger trigger with button it works perfectly fine.另一件事是,如果您删除更新和线程中的 While 循环,并使用按钮触发触发器,它工作得非常好。 But that is of no use to me for my App但这对我的应用程序没有用
please can any one tell whats actually happening and how can I update the image texture using thread.请任何人告诉我实际发生了什么以及如何使用线程更新图像纹理。
Thanks谢谢
I've been bitten by what I think is the same problem that you are encountering.我一直被我认为与您遇到的相同问题所困扰。 As I am sure you know, changes to the GUI must be made on the main thread.我相信您知道,必须在主线程上对 GUI 进行更改。 Your on_a()
and on_newtexture()
will always be run on the main thread, so it would seem that everything is fine in that area.您的on_a()
和on_newtexture()
将始终在主线程上运行,因此该区域的一切似乎都很好。 However, the Texture
class handles OpenGL
textures and I believe that forces the same constraint on using the blit_buffer()
method of Texture
.但是, Texture
class 处理OpenGL
纹理,我相信这对使用Texture
的blit_buffer()
方法有相同的约束。 So here is a modified version of your Main
Widget
that works for me, using Clock.schedule_once()
to get the call to blit_buffer()
back on the main thread:因此,这是一个适用于我的Main
Widget
的修改版本,使用Clock.schedule_once()
在主线程上恢复对blit_buffer()
的调用:
class Main(Widget):
btn1 = ObjectProperty(None)
label1 = ObjectProperty(None)
img1 = ObjectProperty(None)
a = ObjectProperty(1)
newtexture = ObjectProperty(2)
update = False
iter = 1
def btn(self):
self.update = not self.update
t1 = threading.Thread(target=self.updateValue, daemon=True)
t1.start()
# self.updateValue()
def updateValue(self):
while (self.update):
self.a += 2
testexture = Texture.create(size=(512, 512), colorfmt='rgb')
size = 512 * 512 * 3
if self.iter == 1:
buf = [int(x % 128) for x in range(size)]
self.iter = 0
# print("strip")
else:
buf = [int(x % 256) for x in range(size)]
self.iter = 1
# print("random")
buf = bytearray(buf)
Clock.schedule_once(partial(self.updateTexture, testexture, buf))
# print("Generated")
def updateTexture(self, testexture, buf, *args):
testexture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
self.newtexture = testexture
def on_a(self, instance, value):
print('My property a changed to', value)
self.label1.text = str(value)
def on_newtexture(self, instance, value):
self.img1.texture = value
self.img1.canvas.ask_update()
print("updated texture")
print(value)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.