I'm trying to make the text of a button change like a typewriter effect but ran into a problem. While the program is sleeping, the value of the text doesn't actually change until it's done. After 12 seconds (the text im passing over has 12 characters, and the program sleeps for 1 second after each one) the text for the button updates, but I'm trying to get it to update every character. Is there a fix for this?
import time
import asyncio
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.screenmanager import FadeTransition
Builder.load_file("test.kv")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
pass
class CandLApp(App):
def build(self):
sm = ScreenManager(transition=FadeTransition())
sm.add_widget(FirstScreen(name="first"))
sm.add_widget(SecondScreen(name="second"))
return sm
def text_wait(self, text, idforbutton):
anything = getattr(self.root.get_screen("second").ids, idforbutton)
anything.text = ""
for i in text:
anything.text = i
print(anything.text)
time.sleep(1) # the value of text for the button in the second screen doesn't change until
# this entire for loop is done running
if __name__ == "__main__":
CandLApp().run()
.kv file:
<FirstScreen>:
Button:
size_hint: (.274, .2)
pos_hint: {"x":.067, "y":.049}
font_size: 45
color: 200/255, 0/255, 70/255, 1
text: "Test"
on_release: root.manager.current = "second"
<SecondScreen>:
FloatLayout:
Button:
id: buttonfortext
text: "button"
pos_hint: {"center_x": .5, "center_y": .5}
size_hint: .2, .2
on_release: app.text_wait("sending this", "buttonfortext")
CodePudding user response:
If you want to print the text in a typewriter way you can use:
import sys
from time import sleep
def typewriter_print(word)
for char in word:
sleep(1)
sys.stdout.write(char)
sys.stdout.flush()
then you can call the typewriter_print(word) like this
def text_wait(self, text, idforbutton):
anything = getattr(self.root.get_screen("second").ids, idforbutton)
anything.text = ""
typewriter_print(text)
CodePudding user response:
Expanding on my answer above:
Create a callback function that goes through the characters of the text one by one, and returns False when it's done
def handle_char(self, iterator, anything ):
try:
anything = next(iterator)
print(anything)
return True
except StopIteration:
return False
and then call this callback function every second.
def text_wait(self, text, idforbutton):
...
Clock.schedule_interval(lambda dt: self.handle_char(iter(text), anything), 1.0)