问题描述
我有一个套接字客户端,它每次收到消息时都会调用 View()
类.我已经以这样一种方式拆分了我的代码,这样这个类就可以简单地使用 print()
或我喜欢的任何其他显示方法.然而,Kivy 似乎并不喜欢这种方法.我为我的视图扩展了 Kivy 的 BoxLayout
类,并且可以调用 message()
函数.这个类看起来像这样:
I have a socket client that calls a View()
class every time it receives a message. I've split my code in such a way such that this class can simply use print()
or any other display method, as I like. However, it seems that Kivy is not fond of this method. I've extended Kivy's BoxLayout
class for my view and can call the message()
function. The class looks something like this:
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))
message 函数确实被调用并打印但界面没有更新.但是,当我按下按钮时,它会更新界面和打印.
The message function is indeed called and it prints but the interface does not update. When I press the button however, it does update the interface as well as print.
我研究过使用 StringProperty
来修改按钮文本,但也失败了.顺便说一句,如果我正在做的事情完全不可行,我会尝试稍后以板的形式绘制一个由 width * height
按钮组成的整个界面.
I've looked into using a StringProperty
to modify the button text but have failed that too. Just as a note, in case what I'm doing is completely infeasible, I'm trying to later draw an entire interface consisting of width * height
buttons, in the form of a board.
非常感谢任何意见,这让我发疯了.
Any input is very much appreciated, it's been driving me insane.
编辑 1*我关注了一些评论并尝试了一些事情.我添加了一个
Clock
类并让它从 View
安排一个 update()
方法.update 方法只是改变一些元素的文本.当我安排它时,我注意到它可以工作,如下所示:
EDIT 1* I've followed on a few comments and tried a few things out. I've added a
Clock
class and have it schedule an update()
method from View
. The update method simply changes the text of a few elements. I've noticed it works when I schedule it to, as shown below:
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()
所示.周期性触发的 update()
方法也可以工作,分配随机文本.但是现在的问题是它无法设置文本.这不起作用:
The thread now simply assigns the text property as seen in message()
. The periodically triggered update()
methods works too, assigning random text. Now the issue however that it cannot set the text. This does not work:
def update(self, *args, **kwargs):
self.btn.text = self.text
我肯定在其他地方做错了,有什么建议吗?
I must be doing wrong elsewhere, any suggestions?
编辑 2*我要调试的错误是 here.
推荐答案
由于您没有发布完整的工作示例,我只能猜测您在做什么.似乎您在线程上有一个事件(传入消息),并且您希望在发生这种情况时显示一些文本.您需要将 UI 更新推送"到主线程,但您不需要使用 Clock
进行 周期性 更新,您可以使用 Clock.schedule_once
.
Since you don't post a full working example, I can only guess at what your doing. It seems you have an event (incoming message) on a thread, and you want to display some text when this occurs. You need to 'push' UI updates to the main thread, but you don't need to do periodic updates with Clock
, you can just schedule one-time calls with Clock.schedule_once
.
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
装饰器:
As inclement mentioned, you can do this 'push to main thread' automatically with the @mainthread
decorator:
@mainthread
def update(self, text):
self.btn.text = text
def message(self, message):
update(message)
这样,每当你调用 update
时,它都会在主线程上执行.
This way, whenever you call update
it will be executed on the main thread.
这篇关于如何从线程更新 Kivy 元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!