【问题标题】:Threading Problem Kivy image texture not updating when threading is used线程问题 Kivy 图像纹理在使用线程时不更新
【发布时间】:2020-05-24 05:20:36
【问题描述】:

我正在尝试使用 Kivy 制作一个使用线程的应用程序。后台线程更新 Image Widget 主类中的纹理。

问题是纹理变量已更新但未显示在 kivy Gui 应用程序中

这是代码 我使用 ObjectProperty 来触发更新 label:textImage: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()

如果您在 update And Threading 中删除 While 循环,并使用按钮触发触发器,则它工作得非常好。但这对我的应用程序没有用

请任何人告诉我实际发生了什么以及如何使用线程更新图像纹理。

谢谢

【问题讨论】:

    标签: python multithreading kivy


    【解决方案1】:

    我一直被我认为与您遇到的相同问题所困扰。我相信您知道,必须在主线程上对 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)
    

    【讨论】:

      猜你喜欢
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-26
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      相关资源
      最近更新 更多