how can i access ids in kivy screenmanger - python

main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
class ScreenHome(Screen):
pass
class ScreenNew(Screen):
pass
class Performer(App):
def build(self):
sm = ScreenManager()
sm.add_widget(ScreenHome(name="home"))
sm.add_widget(ScreenNew(name="new"))
return sm
def test(self):
text = self.root.get_screen('<ScreenNew>').mytext
label = self.root.get_screen('<ScreenNew>').mylabel
label.text = text.text
pass
if __name__ == '__main__':
Performer().run()
kv file
<ScreenHome>:
Button:
text: 'Home'
on_press: app.root.current = 'new'
<ScreenNew>:
GridLayout:
rows: 4
Label:
id: mylabel
TextInput:
id: mytext
Button:
on_press: app.test()
text: "adauga"
font_size: 50
Button:
text: 'Home'
on_press: app.root.current = 'home'

Related

How do i get 2 TextInput values through the id

So i have the class which has to create task and it looks like this
class CreateTask(Screen):
def CreateTask(self,*args):
bl = BoxLayout(orientation="vertical",spacing=10)
name=self.root.ids.TaskName.text
desc=self.root.ids.TaskDesc.text
bl.add_widget(name)
bl.add_widget(desc)
self.root.MainLayout.add_widget(bl)
but i get the error 'CreateTask' object has no attribute 'root', so how do i get the text from 2 TextInputs through the id?
and here is my kv code for that class
<CreateTask>
name:"third"
AnchorLayout:
size:root.size
anchor_x:"center"
anchor_y:"top"
BoxLayout:
orientation:"vertical"
size_hint:[0.6,0.6]
Label:
text:"Input Task Name"
TextInput:
size_hint:[0.2,0.2]
id:"TaskName"
TextInput:
size_hint:[0.6,0.6]
id:"TaskDesc"
multiline:False
Button:
size_hint:[0.4,0.4]
text:"come_back"
on_release:
app.root.current ="second"
root.manager.transition.direction = "left"
Button:
size_hint:[0.4,0.4]
text:"Create"
on_release:root.CreateTask(*args)
here is the MainLayout
BoxLayout:
size_hint:[0.4,0.2]
id:MainLayout
orientation:"vertical"
Button:
size_hint:[0.3,0.3]
text:"Add Task"
on_release:
app.root.current="third"
root.manager.transition.direction = "right"
also it looks like there is an error with tabulation, there is not, it's just pasted like that
'CreateTask' object has no attribute 'root' because 'self' is already the root. And do not use string as id.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
class CreateTask(Screen):
def CreateTask(self, *args):
bl = BoxLayout(orientation="vertical",spacing=10)
name=self.ids.TaskName.text
desc=self.ids.TaskDesc.text
lbl_name = Label(text=name)
lbl_desc = Label(text=desc)
bl.add_widget(lbl_name)
bl.add_widget(lbl_desc)
self.ids.MainLayout.add_widget(bl)
sm = ScreenManager()
Builder.load_file("mainscreen.kv")
sm.add_widget(CreateTask())
class MainScreenApp(App):
def build(self):
return sm
if __name__ == "__main__":
MainScreenApp().run()
<CreateTask>
name:"third"
AnchorLayout:
size:root.size
anchor_x:"center"
anchor_y:"top"
BoxLayout:
orientation:"vertical"
size_hint:[0.6,0.6]
Label:
text:"Input Task Name"
TextInput:
size_hint:[0.2,0.2]
id: TaskName
TextInput:
size_hint:[0.6,0.6]
id: TaskDesc
multiline:False
Button:
size_hint:[0.4,0.4]
text:"come_back"
on_release:
app.root.current: "second"
root.manager.transition.direction: "left"
Button:
size_hint:[0.4,0.4]
text:"Create"
on_release: root.CreateTask(*args)
BoxLayout:
size_hint:[0.4,0.2]
id:MainLayout
orientation:"vertical"
Button:
size_hint:[0.3,0.3]
text:"Add Task"
on_release:
app.root.current="third"
root.manager.transition.direction = "right"

How could I make text input screen after changing the text is automatically deleted, when I go back to login screen

imports:
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
kv = '''
<Login>
name:'Login'
ben: benName.text
pw: passwort.text
knopf: btn
knopff: btnn
GridLayout:
cols: 1
size: root.width,root.height
GridLayout:
cols: 2
Label:
text: "Username"
font_size: 25
TextInput:
id: benName
multiline: False
font_size: 30
Label:
text: "Password"
font_size: 25
bold: True
TextInput:
password: True
id: passwort
multiline: False
font_size: 40
Button:
size_hint: (1.,1.10)
text:" Start "
id: btn
font_size: 40
on_release:
root.manager.current = "data" if passwort.text == "1" and benName.text == "1" else "Login"
root.manager.transition.direction = "down"
Button:
size_hint: (1.,1.10)
text: " Exit "
id: btnn
font_size: 40
on_release: app.stop()
<data>
BoxLayout:
orientation: "vertical"
Label:
text:
"hallo"
Button:
text: " back "
on_press:
root.clear_inputs()
root.manager.current = "Login"
'''
MyApp class:
class Login(Screen):
ben = StringProperty()
pw = StringProperty()
knopf = ObjectProperty()
class MyApp(App):
Builder.load_string(kv)
def build(self):
ms = ScreenManager()
ms.add_widget(Login(name='Login'))
ms.add_widget(data(name='data'))
self.title = "MyApp"
return ms
class data(Screen):
def clear_inputs(self):
login = self.manager.get_screen('Login')
for child in reversed(login.ids.container.children):
if isinstance(child, TextInput):
child.text = ''
if __name__ == '__main__':
MyApp().run()
Just access their IDs in a method and then set their text to "" when entering screen, by using on_pre_enter, this method is fired whenever u enter the screen, even if you leave and enter again, it will run
class Login (Screen):
def on_pre_enter(self):
self.ids['benName'].text = ""
self.ids['passwort'].text = ""

Kivy - CustomDropdown - ScreenManager - failure

I´m trying to add a CustomDropDown to a button, but somehow it seems like the CustomDropDown-widget is initiated twice (dubble list) and when I click on a name I get the following answer:
Error:
File "C:\Continuum\anaconda3\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
exec(__kvlang__.co_value, idmap)
File "C:\Temp\privat\zucchini\my.kv", line 6, in <module>
app.root.ids.btn.text = '{}'.format(args[1])
File "kivy\properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
So yes, I fail to see what I´m doing wrong.. And thoughts are welcome! :)
CODE:
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class WindowManager(ScreenManager):
pass
class MainWindow(Screen):
dropdown = ObjectProperty(None)
def __init__(self, **kw):
super().__init__(**kw)
self.cols = 1
class SecondWindow(Screen):
pass
class MyApp(App):
"""
"""
def build(self):
return Builder.load_file("my.kv")
if __name__ == "__main__":
MyApp().run()
With the kv-file looking like:
#:import Factory kivy.factory.Factory
<CustomDropDown#DropDown>:
id: dropdown
on_select:
app.root.ids.btn.text = '{}'.format(args[1])
self.dismiss()
Button:
id: btn1
text: 'name1'
size_hint_y: None
height: '32dp'
on_release:
dropdown.select(btn1.text)
Button:
id: btn2
text: 'name2'
size_hint_y: None
height: '32dp'
on_release:
dropdown.select(btn2.text)
Button:
id: btn3
text: 'name3'
size_hint_y: None
height: '32dp'
on_release:
dropdown.select(btn3.text)
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
GridLayout:
cols: 1
GridLayout:
cols: 1
GridLayout:
cols: 1
GridLayout:
cols: 2
Button:
id: btn
text: 'Set name'
on_release: Factory.CustomDropDown().open(self)
Button:
text: "Submit"
on_release:
app.root.current = "second"
root.manager.transition.direction = "right"
<SecondWindow>:
name: "second"
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "left"
Firstly mate, you forgot to add to from kivy.app import App on your .py file.This code not giving me twice your button.It looks correct and gave me only 3 button as you wish.I showed you below how you can call which button clicked.And i suggest you that you can create these 3 button in .py file with a loop easily.Because these are looks like same.I hope this codes help you.
Its my code:
My .py file:
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.dropdown import DropDown
class CustomDropDown(DropDown):
def give_my_value(self,value):
print('Selected value is :',value)
class WindowManager(ScreenManager):
pass
class MainWindow(Screen):
dropdown = ObjectProperty(None)
def __init__(self, **kw):
super().__init__(**kw)
self.cols = 1
class SecondWindow(Screen):
pass
class MyApp(App):
"""
"""
def build(self):
return Builder.load_file("my.kv")
if __name__ == "__main__":
MyApp().run()
my.kv file:
#:import Factory kivy.factory.Factory
<CustomDropDown#DropDown>:
id: dropdown
on_select:
self.dismiss()
Button:
id: btn1
text: 'name1'
size_hint_y: None
height: '32dp'
on_release:
dropdown.give_my_value(self.text)
dropdown.dismiss()
Button:
id: btn2
text: 'name2'
size_hint_y: None
height: '32dp'
on_release:
dropdown.give_my_value(self.text)
dropdown.dismiss()
Button:
id: btn3
text: 'name3'
size_hint_y: None
height: '32dp'
on_release:
dropdown.give_my_value(self.text)
dropdown.dismiss()
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
GridLayout:
cols: 1
GridLayout:
cols: 1
GridLayout:
cols: 1
GridLayout:
cols: 2
Button:
id: btn
text: 'Set name'
on_release: Factory.CustomDropDown().open(self)
Button:
text: "Submit"
on_release:
app.root.current = "second"
root.manager.transition.direction = "right"
<SecondWindow>:
name: "second"
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "left"

Using a spinner and button together to change screens

I found this code that showed me how to use a spinner to change screens. It works well in allowing me to switch screens, but I found that I also need to switch screens by using buttons on an individual screen.
Here is an example of what I mean:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.spinner import Spinner
KV = """
<MainScreen>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Edit'
on_press: root.goEdit()
Label:
text: 'Main Screen'
<HelpScreen>:
Label:
text: 'Help Screen'
<SettingsScreen>:
Label:
text: 'Settings Screen'
<EditScreen>:
name: 'edit_Screen'
text: 'Edit Screen'
<ScreenMenu>:
text: 'main'
values: ('main', 'help', 'settings')
size_hint: None, None
size: 200, 44
"""
class MainScreen(FloatLayout):
def goEdit(self):
MyApp.build.screen_layout.remove_widget(MyApp.screen)
screen = EditScreen()
MyApp.screen = screen
MyApp.screen_layout.add_widget(MyApp.screen)
class HelpScreen(FloatLayout):
pass
class SettingsScreen(FloatLayout):
pass
class EditScreen(FloatLayout):
pass
class ScreenMenu(Spinner):
pass
class MyApp(App):
def build(self):
Builder.load_string(KV)
self.screen = None
self.root = FloatLayout()
self.screen_layout = FloatLayout()
self.menu = ScreenMenu()
self.root.add_widget(self.screen_layout)
self.root.add_widget(self.menu)
self.menu.bind(text=self.select_screen)
self.show('main')
return self.root
def select_screen(self, *args):
self.show(self.menu.text)
def show(self, name='main'):
if self.screen is not None:
self.screen_layout.remove_widget(self.screen)
self.screen = None
if name == 'main':
screen = MainScreen()
elif name == 'help':
screen = HelpScreen()
elif name == 'settings':
screen = SettingsScreen()
else:
raise Exception('Invalid screen name')
self.screen = screen
self.screen_layout.add_widget(screen)
if __name__ == "__main__":
MyApp().run()
As you can see, this is almost the exact code as found in the link above, the only difference is that here, I create an "Edit" button that when clicked, refers to the goEdit() method of the "MainScreen" class.
on_press: root.goEdit()
My problem is I don't know how to create the goEdit() method so that, when called, it goes to the "EditScreen" while also having the spinner work ( it goes to the "MainScreen", "HelpScreen" and "SettingScreen" screens). The code I tried in goEdit() clearly doesn't work.
I have also tried changing the inherited classes from FloatLayout to Screen:
class MainScreen(Screen):
def goEdit(self):
self.parent.current = 'edit_Screen'
class HelpScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class EditScreen(Screen):
pass
class ScreenMenu(Spinner):
pass
Here I tried to switch screens using this code:
self.parent.current = 'edit_Screen'
but when clicking the 'edit' button, nothing happens, I don't even get error messages.
Essentially what I want is for the spinner to work as it does in the example link, but I also need the 'edit' button to also change screens. Any help would be greatly appreciated.
Solution
Please refer to the explanations, example and output for details.
kv String
Replace root.edit() with app.show(name='edit')
Replace name: 'edit_screen' with Label:
Indent text: 'Edit Screen'
Python Script
Replace all the codings in MainScreen with pass
Add elif name == 'edit': screen = EditScreen() statement in method show
Example
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.spinner import Spinner
KV = """
<MainScreen>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Edit'
on_press: app.show(name='edit')
Label:
text: 'Main Screen'
<HelpScreen>:
Label:
text: 'Help Screen'
<SettingsScreen>:
Label:
text: 'Settings Screen'
<EditScreen>:
Label:
text: 'Edit Screen'
<ScreenMenu>:
text: 'main'
values: ('main', 'help', 'settings')
size_hint: None, None
size: 200, 44
"""
class MainScreen(FloatLayout):
pass
class HelpScreen(FloatLayout):
pass
class SettingsScreen(FloatLayout):
pass
class EditScreen(FloatLayout):
pass
class ScreenMenu(Spinner):
pass
class MyApp(App):
def build(self):
Builder.load_string(KV)
self.screen = None
self.root = FloatLayout()
self.screen_layout = FloatLayout()
self.menu = ScreenMenu()
self.root.add_widget(self.screen_layout)
self.root.add_widget(self.menu)
self.menu.bind(text=self.select_screen)
self.show('main')
return self.root
def select_screen(self, *args):
self.show(self.menu.text)
def show(self, name='main'):
if self.screen is not None:
self.screen_layout.remove_widget(self.screen)
self.screen = None
if name == 'main':
screen = MainScreen()
elif name == 'help':
screen = HelpScreen()
elif name == 'settings':
screen = SettingsScreen()
elif name == 'edit':
screen = EditScreen()
else:
raise Exception('Invalid screen name')
self.screen = screen
self.screen_layout.add_widget(screen)
if __name__ == "__main__":
MyApp().run()
Output
Here is a very simple example using the ScreenManager:
Python
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class Screen3(Screen):
pass
class MyScreenManager(ScreenManager):
def changescreen(self, value):
try:
if value!='Choose a Value...':
self.current = value
except:
print('No screen named ' + value)
#Main application
class TestApp(App):
def build(self):
self.sm = MyScreenManager()
return self.sm
if __name__ == '__main__':
TestApp().run()
kv
<MyScreenManager>:
Screen1:
name: 'screen1'
Screen2:
name: 'screen2'
Screen3:
name: 'screen3'
<Screen1>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 2'
on_press: root.manager.current = 'screen2'
Button:
text: 'Go to Screen 3'
on_press: root.manager.current = 'screen3'
Spinner:
text: 'Choose a Value...'
values: ['screen2', 'screen3']
on_text:
root.manager.changescreen(self.text)
self.text = 'Choose a Value...'
Label:
text: 'You are on ' + root.name
<Screen2>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 1'
on_press: root.manager.current = 'screen1'
Button:
text: 'Go to Screen 3'
on_press: root.manager.current = 'screen3'
Spinner:
text: 'Choose a Value...'
values: ['screen1', 'screen3']
on_text:
root.manager.changescreen(self.text)
self.text = 'Choose a Value...'
Label:
text: 'You are on ' + root.name
<Screen3>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 1'
on_press: root.manager.current = 'screen1'
Button:
text: 'Go to Screen 2'
on_press: root.manager.current = 'screen2'
Spinner:
text: 'Choose a Value...'
values: ['screen1', 'screen2']
on_text:
root.manager.changescreen(self.text)
self.text = 'Choose a Value...'
Label:
text: 'You are on ' + root.name

Kivy with Menubar

I want to create a Kivy-App with a Menubar which is always the same.
My Code:
demo.py:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
class Display(BoxLayout):
pass
class Screen_One(Screen):
pass
class Screen_Two(Screen):
pass
class DemoApp(App):
def build(self):
return Display()
if __name__ == '__main__':
DemoApp().run()
demo.kv:
<Display>:
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1, None
height: '48dp'
Button:
text: 'One'
on_release: sm.current = 'Screen_One'
Button:
text: 'Two'
on_release: sm.current = 'Screen_Two'
ScreenManager:
id: sm
Screen_One:
Screen_Two:
<Screen_One>:
Button:
text: 'One'
<Screen_Two>:
Button:
text: 'Two'
But it doesn't work, if i click on "One" i received:
kivy.uix.screenmanager.ScreenManagerException: No Screen with name "Screen_One".
I reduced my code to the leading part. I also tried to put the menu-kivy-code in a seperate file and import but then i also can't access the ScreenManager and can't switch the Screens.
ScreenManager.current atribute is the name of the screen currently shown. You have not set the name attribute in your classes (screens). Your demo.kv file should be:
<Display>:
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1, None
height: '48dp'
Button:
text: 'One'
on_release: sm.current = 'screen_one' #<<<<<<<<<<<<<<<<
Button:
text: 'Two'
on_release: sm.current = 'screen_two' #<<<<<<<<<<<<<<<<
ScreenManager:
id: sm
Screen_One:
Screen_Two:
<Screen_One>:
name: 'screen_one' #<<<<<<<<<<<<<<<<
Button:
text: 'One'
<Screen_Two>:
name: 'screen_two' #<<<<<<<<<<<<<<<<
Button:
text: 'Two'

Categories