简体   繁体   English

线程问题 Kivy 使用线程时图像纹理未更新

[英]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: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()

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纹理,我相信这对使用Textureblit_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM