如何从线程更新Kivy元素?

时间:2015-11-19 16:22:45

标签: python kivy python-multithreading

我有一个套接字客户端,每次收到消息时都会调用View()类。我已经以这样的方式拆分我的代码,以便这个类可以简单地使用print()或任何其他显示方法,如我所愿。然而,似乎Kivy并不喜欢这种方法。我为我的观点扩展了Kivy的BoxLayout类,可以调用message()函数。该课程看起来像这样:

class View(BoxLayout):
    def __init__(self, **kwargs):
        super(View, self).__init__(**kwargs)
        self.btn = Button(text='Default')
        # Bind button press method
        self.btn.bind(on_press=self.message)
        self.add_widget(self.btn)
    def message(self, message):
        self.btn.text = 'Meow'
        self.add_widget(Button(text='Meow'))
        print(str(message))

确实调用了消息函数并打印但接口未更新。但是,当我按下按钮时,它会更新界面以及打印。

我已经研究过使用StringProperty来修改按钮文本,但也失败了。就像一张纸条,如果我正在做的事情是完全不可行的,我试图稍后以棋盘形式绘制一个由width * height按钮组成的整个界面。

非常感谢任何投入,这让我疯狂。


编辑1 * 我接下来发表了一些评论并尝试了一些方法。我添加了Clock课程,并安排update()来自View的{​​{1}}方法。 update方法只是更改了一些元素的文本。我注意到它在我安排时有效,如下所示:

def update(self, *args, **kwargs):
    self.btn.text = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for i in range(32))
def message(self, message):
    try:
        print(message)
        self.text = 'sending'
    except Exception as e:
        print(e)

线程现在只是分配message()中所见的text属性。定期触发的update()方法也可以工作,分配随机文本。现在问题是它无法设置文本。这不起作用:

def update(self, *args, **kwargs):
    self.btn.text = self.text

我一定在其他地方做错了,有什么建议吗?


编辑2 * 我正在尝试调试的错误是here

1 个答案:

答案 0 :(得分:4)

由于您没有发布完整的工作示例,我只能猜测您的工作。您似乎在某个线程上有一个事件(传入消息),并且您希望在发生这种情况时显示一些文本。您需要将UI更新“推送”到主线程,但您不需要使用Clock执行定期更新,您只需使用{{1}安排一次性调用}。

Clock.schedule_once

正如提到的那样,您可以使用@mainthread装饰器自动执行“推送到主线程”:

from functools import partial

def update(self, text, *a):
    self.btn.text = text

def message(self, message):
    Clock.schedule_once(partial(self.update, message), 0)

这样,无论何时调用@mainthread def update(self, text): self.btn.text = text def message(self, message): update(message) ,它都将在主线程上执行。