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:
我有一个套接字客户端,每当它收到消息时就调用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))
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.
消息函数确实被调用并打印,但是接口没有更新。当我按下按钮时,它会更新界面和打印。
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.
我曾考虑过使用StringProperty来修改按钮文本,但也失败了。就像一个注释,如果我做的是完全不可行的,我试着以后画一个完整的界面,包括宽度*高度的按钮,以一个板的形式。
Any input is very much appreciated, it's been driving me insane.
非常感谢你的建议,它让我发疯。
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)
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:
线程现在只需分配message()中的text属性。周期性触发的update()方法也可以工作,分配随机文本。然而,现在的问题是它不能设置文本。这并不工作:
def update(self, *args, **kwargs):
self.btn.text = self.text
I must be doing wrong elsewhere, any suggestions?
我在别的地方一定做错了,有什么建议吗?
EDIT 2* The error I'm trying to debug is here.
1 个解决方案
#1
3
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
.
既然你没有发布一个完整的工作示例,我只能猜测你在做什么。似乎您在线程上有一个事件(传入消息),并且您希望在发生该事件时显示一些文本。您需要“推送”UI更新到主线程,但不需要使用时钟进行周期性更新,只需使用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)
As inclement mentioned, you can do this 'push to main thread' automatically with the @mainthread
decorator:
正如前面提到的,您可以使用@mainthread decorator自动地执行“推到主线程”:
@mainthread
def update(self, text):
self.btn.text = text
def message(self, message):
update(message)
This way, whenever you call update
it will be executed on the main thread.
这样,无论何时调用update,它都将在主线程上执行。
#1
3
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
.
既然你没有发布一个完整的工作示例,我只能猜测你在做什么。似乎您在线程上有一个事件(传入消息),并且您希望在发生该事件时显示一些文本。您需要“推送”UI更新到主线程,但不需要使用时钟进行周期性更新,只需使用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)
As inclement mentioned, you can do this 'push to main thread' automatically with the @mainthread
decorator:
正如前面提到的,您可以使用@mainthread decorator自动地执行“推到主线程”:
@mainthread
def update(self, text):
self.btn.text = text
def message(self, message):
update(message)
This way, whenever you call update
it will be executed on the main thread.
这样,无论何时调用update,它都将在主线程上执行。