我正试图用Kivy制作一个使用线程的应用程序。后台线程更新Image Widget主类中的纹理,问题是纹理变量被更新,但在kivy Gui应用中却没有显示。
问题是纹理变量被更新了,但在kivy Gui应用程序中却没有显示出来。
以下是我使用的代码 对象属性 同时触发更新 标签:文本 和 图片:纹理 但是,只有 标签:文本 日新月异
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()
另一件事,如果你删除更新和线程中的while循环,并只是触发触发按钮,它的工作完全正常。但是,这是对我的应用程序没有用的我
请有谁能告诉我到底发生了什么,我怎么能用线程更新图像纹理。
谢谢你
我已经被我认为和你遇到的相同的问题所困扰了。我相信你也知道,对GUI的修改必须在主线程上进行。你的 on_a()
和 on_newtexture()
将始终在主线程上运行,因此在该领域似乎一切正常。然而,在主线程上运行的 Texture
类处理 OpenGL
纹理,我相信这也会对使用 blit_buffer()
方式 Texture
. 所以这里有一个修改版的你的 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)