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))
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.
Any input is very much appreciated, it's been driving me insane.
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:
def update(self, *args, **kwargs):
self.btn.text = self.text
I must be doing wrong elsewhere, any suggestions?
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)
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)
This way, whenever you call update
it will be executed on the main thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With