I have been trying to create an app with Kivy that receives 0, 1 or 2 as text input by the user (it will be specified in the first screen that the user should only type 0, 1 or 2 as input) and in the final screen shows a label text which differs based on that input. When I try to run it, it will not start due to a NameError in the final line of code in the .kv file.
What I would like to know is how i can define the name in the NameError or if I can define the ids of the text inputs as variables in order to overcome the error.
I do realise a lot of very similar questions have been asked before here and on other sites and I have tried implementing the answers, yet they do not work. My background in programming is practically non-existent, so please be as elaborate as you can in your answers if you feel like it. Thank you in advance for your time and following are the codes of the .py and .kv files as well as a part the error.
Edit: Thank you all for your comments and answers. The error has been fixed by implementing your recommendations and I am now able to run the app. However, another problem has come up. On the fourth screen only the text of the "else statement" ("Bad Luck") is printed in the label even when the requirements of the "if statement" are met. Any ideas or suggestions would be deeply appreciated.
.py file:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, StringProperty, NumericProperty
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
pass
class FourthWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class MyApp(App):
def build(self):
kv = Builder.load_file("my.kv")
return kv
if __name__=="__main__":
MyApp().run()
.kv file:
WindowManager:
MainWindow:
SecondWindow:
ThirdWindow:
FourthWindow:
<MainWindow>:
name: "main"
GridLayout:
cols:1
rows:2
Label:
text: "stuff"
Button:
text: "stuff"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
GridLayout:
cols:1
rows:2
GridLayout:
cols:2
Label:
text: "stuff"
TextInput:
id: ti_a
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_b
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_c
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_d
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_e
multiline:False
GridLayout:
cols:2
Button:
text: "stuff"
on_release:
app.root.current = "third"
root.manager.transition.direction = "left"
Button:
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
<ThirdWindow>:
name: "third"
GridLayout:
cols:1
rows:2
GridLayout:
cols:2
Label:
text: "stuff"
TextInput:
id: ti_f
multiline:False
GridLayout:
cols:2
Button:
text: "stuff"
on_release:
app.root.current = "fourth"
root.manager.transition.direction = "left"
Button:
text: "Back"
on_release:
app.root.current = "second"
root.manager.transition.direction = "right"
<FourthWindow>:
name: "fourth"
Label:
text:"stuff" if root.manager.screens(second).ids.ti_a.text == "0" and root.manager.screens(second).ids.ti_b.text == "0" and root.manager.screens(second).ids.ti_c.text == "0" and root.manager.screens(second).ids.ti_d.text == "0" and root.manager.screens(second).ids.ti_e.text == "1" and root.manager.screens(third).ids.ti_f.text == "0" else "Bad Luck"
Error:
BuilderException: Parser: File "C:\Users\NIK\Desktop\my.kv", line 106:
104: name: "fourth"
105: Label:
>> 106: text:"stuff" if root.manager.screens(second).ids.ti_a.text == "0" and root.manager.screens(second).ids.ti_b.text == "0" and root.manager.screens(second).ids.ti_c.text == "0" and root.manager.screens(second).ids.ti_d.text == "0" and root.manager.screens(second).ids.ti_e.text == "1" and root.manager.screens(third).ids.ti_f.text == "0" else "Bad Luck"
107:
108:
NameError: name 'second' is not defined
To get a screen from the screen manager either you have to use id
of the screen or use get_screen("screen_name")
. In your code, I don't see any one them. What you can do is give all screens an id
and then use root.manager.<screen_id>.ti_a.text
and so on. Or you can use get_screen
to get screen by its name which you have given in your code. It will be like root.manager.get_screen("second").ti_a.text
and so on. I would say use later one as you have already given names. This is how it will look:
text:"stuff" if root.manager.get_screen("second").ids.ti_a.text == "0" and root.manager.get_screen("second").ids.ti_b.text == "0" and root.manager.get_screen("second").ids.ti_c.text == "0" and root.manager.get_screen("second").ids.ti_d.text == "0" and root.manager.get_screen("second").ids.ti_e.text == "1" and root.manager.get_screen("third").ids.ti_f.text == "0" else "Bad Luck"