I'd like the App to change screen from the EntryWindow screen to the Home screen, after like one second. Since I had already problems with the ScreenManager current property to actually switch screens, I didn't try to even use Clock to trigger the switch after one second of EntryWindow. Could someone help me with this? I have python version 3.12, kivy version 2.3.0 and kivymd version 1.2.0. This is my .py file:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.metrics import dp
from kivy.core.window import Window
from kivy.clock import Clock
import random as rd
Window.size = (360,640)
class MainApp(MDApp):
def build(self):
screen = Builder.load_file("myKv.kv")
self.theme_cls.primary_palette ="Orange"
self.theme_cls.primary_hue = "A700"
self.theme_cls.theme_style="Dark"
return screen
class EntryWindow(Screen):
def on_enter(self):
sm.current = "home"
class Home(Screen):
pass
class Exercises(Screen):
pass
class Gender(Screen):
def on_enter(self):
self.ids.extractedWord.color = (1,1,1,1)
f = open(".venv/genderWordDatabase.txt")
red = f.readlines()
stripped = [elem.strip() for elem in red]
separato = [elem.split() for elem in stripped]
dizWords = {}
for i in separato:
dizWords[i[1]] = (i[0],i[2])
print(dizWords)
extracted = list(dizWords.keys())[rd.randint(0,len(dizWords)-1)]
self.ids.extractedWord.font_style = "H6"
self.ids.extractedWord.text = extracted
def recordUpdate(self,extractedWord,operand):
f = open(".venv/genderWordDatabase.txt", "r")
red = f.readlines()
f.close()
for i in range(0,len(red)):
if extractedWord in red[i]:
red[i] = " ".join(red[i].strip("\n").split()[:-1]) + " " + str(int(red[i].strip("\n").split()[2])+operand)+"\n"
g = open(".venv/genderWordDatabase.txt", "w")
g.writelines(red)
def wordExtraction(self):
self.ids.extractedWord.color = (1,1,1,1)
f = open(".venv/genderWordDatabase.txt")
red = f.readlines()
f.close()
stripped = [elem.strip() for elem in red]
separato = [elem.split() for elem in stripped]
dizWords = {}
for i in separato:
dizWords[i[1]] = (i[0],i[2])
extracted = list(dizWords.keys())[rd.randint(0,len(dizWords)-1)]
self.ids.extractedWord.font_style = "H6"
self.ids.extractedWord.text = extracted
def check(self, answer):
f = open(".venv/genderWordDatabase.txt")
red = f.readlines()
f.close()
stripped = [elem.strip("\n").strip() for elem in red]
separato = [elem.split() for elem in stripped]
dizWords = {}
for i in separato:
dizWords[i[1]] = (i[0],i[2])
print(dizWords)
parola = self.ids.extractedWord.text
if dizWords[parola][0] == answer:
self.ids.extractedWord.color = (0,1,0,1)
self.ids.extractedWord.font_style = "H6"
self.ids.extractedWord.text = "Right +1"
#Chiamo la funzione che aggiorna il record di ciascuna parola
self.recordUpdate(dizWords[parola][0],1)
Clock.schedule_once(lambda dt: self.wordExtraction(), 1)
else:
self.ids.extractedWord.color = (1,0,0,1)
self.ids.extractedWord.font_style = "Body1"
self.ids.extractedWord.text = "Wrong -1, the correct one was: " + dizWords[self.ids.extractedWord.text][0]
self.recordUpdate(dizWords[parola][0],-1)
Clock.schedule_once(lambda dt: self.wordExtraction(), 2)
sm = ScreenManager()
sm.add_widget(EntryWindow(name="starting"))
sm.add_widget(Home(name="home"))
sm.add_widget(Exercises(name="exercises"))
sm.add_widget(Gender(name="gender"))
MainApp().run()
and this is my .kv file:
ScreenManager:
EntryWindow:
Home:
Exercises:
<EntryWindow>:
name: "starting"
BoxLayout:
orientation: "vertical"
Widget:
MDLabel:
text: "German"
halign: "center"
markup: True
color: (1,1,1,1)
font_style: "H3"
MDLabel:
text: "By Staffo"
markup: True
color: (1,1,1,1)
halign: "center"
font_style: "H6"
Widget:
Widget:
<Home>:
name: "home"
AnchorLayout:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: "vertical"
spacing: 30
Widget:
MDFillRoundFlatButton:
text: "exercises"
pos_hint: {"center_x":0.5,"center_y":0.5}
on_press:root.manager.current = "exercises"
MDFillRoundFlatButton:
text: "customize dictionary"
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press:root.manager.current = "customize"
MDFillRoundFlatButton:
text: "Settings"
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press:root.manager.current = "settings"
MDFillRoundFlatButton:
text: "Credits"
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press: root.manager.current = "credits"
Widget:
<Exercises>:
name: "exercises"
AnchorLayout:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: "vertical"
spacing: 30
Widget:
MDFillRoundFlatButton:
text: "[b]M/F/N/P[/b]"
markup: True
pos_hint: {"center_x":0.5,"center_y":0.5}
on_press:root.manager.current = "gender"
text_color: (1,1,1,1)
MDFillRoundFlatButton:
text: "[b]Learn New Words[/b]"
markup: True
text_color: (1,1,1,1)
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press:root.manager.current = ""
MDFillRoundFlatButton:
text: "[b]Phrases[/b]"
markup: True
text_color: (1,1,1,1)
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press:root.manager.current = ""
MDFillRoundFlatButton:
text: "[b]Listening[/b]"
markup: True
text_color: (1,1,1,1)
pos_hint: {"center_x":0.5,"center_y":0.5}
#on_press: root.manager.current = ""
Widget:
<Gender>:
name: "gender"
AnchorLayout:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: "vertical"
Widget:
Widget:
Widget:
MDCard:
size_hint: .85, 2
pos_hint: {"center_x": .5, "center_y": .5}
MDRelativeLayout:
MDLabel:
halign: "center"
id: extractedWord
markup: True
text: "extractedWord"
font_style: "H6"
color: (0,0,0,1)
BoxLayout:
spacing: 20
Widget:
MDFillRoundFlatButton:
text: "[b]der[/b]"
markup: True
text_color: (1,1,1,1)
on_press: root.check("der")
MDFillRoundFlatButton:
text: "[b]die[/b]"
markup: True
text_color: (1,1,1,1)
on_press: root.check("die")
MDFillRoundFlatButton:
text: "[b]das[/b]"
markup: True
text_color: (1,1,1,1)
on_press: root.check("das")
Widget:
Widget:
Widget:
Widget:
Widget:
and I get the following error:
kivy.uix.screenmanager.ScreenManagerException: No Screen with name "home".
The problem is with your on_enter()
method of EntryWindow
. Because your kv
creates an EntryWindow
as the first Screen
, and its on_enter()
method is triggered before the other Screens
are even created. A simple fix is to delay the screen
change a bit using Clock.schedule_once()
, like this:
class EntryWindow(Screen):
def on_enter(self):
# delay the Screen switch
Clock.schedule_once(self.switch_screen)
def switch_screen(self, _dt):
self.manager.current = "home"
As you see, in the switch_screen()
method, I changed sm
to self.manager
. The sm
that you have defined in your code is unused and should be eliminated:
# sm = ScreenManager()
# sm.add_widget(EntryWindow(name="starting"))
# sm.add_widget(Home(name="home"))
# sm.add_widget(Exercises(name="exercises"))
# sm.add_widget(Gender(name="gender"))