Screen Manager in kivy with kv file - python

this is the first question I am posting so sorry if the question is not complete.
I tried the example on kivy's official page for Screen Manager and it works, but if I try using a kv file instead of the Builder, I get a black page.
Test.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MenuScreen(Screen):
pass
class SettingsScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
Test.kv
<MenuScreen>:
BoxLayout:
Button:
text: 'Goto settings'
on_press: root.manager.current = 'settings'
Button:
text: 'Quit'
<SettingsScreen>:
BoxLayout:
Button:
text: 'My settings button'
Button:
text: 'Back to menu'
on_press: root.manager.current = 'menu'

Your test.py should look like:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
# Declare both screens
class MenuScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class TestApp(App):
pass
if __name__ == '__main__':
TestApp().run()
And your test.kv file should be:
#: kivy 1.10.0
ScreenManager:
id: screen_manager
MenuScreen:
id: menu_screen
name: 'menu'
manager: 'screen_manager'
SettingsScreen:
id: settings_screen
name: 'settings'
manager: 'screen_manager'
<MenuScreen>:
BoxLayout:
Button:
text: 'Goto settings'
on_press: app.root.current = 'settings'
Button:
text: 'Quit'
<SettingsScreen>:
BoxLayout:
Button:
text: 'My settings button'
Button:
text: 'Back to menu'
on_press: app.root.current = 'menu'

Related

Geeting error in reading a file and pronting it as Label in kivy

I am trying to read text from a file and show it as Label in another screen but i am getting error that text file's content in not str even after using str() function.
Error:
ValueError: Screen1.usename accept only str
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
def gb(self):
f=open('test.txt','r')
b=f.read()
t=str(b)
return t
usename = StringProperty("")
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
BoxLayout:
orientation: "vertical"
Button:
text:'ue'
on_release: root.usename = root.gb; root.manager.current = "screen2"
<Screen2>:
name: "screen2"
Label:
text: root.username
ScreenManager:
Screen1:
id: loginscreen
Screen2:
username: loginscreen.usename
''')
class MyApp(App):
def build(self):
return root
r=MyApp()
r.run()
Your code:
on_release: root.usename = root.gb
is trying to set the usename to a method (root.gb). You probably want to set usename to the return value of that method. Try just adding (), like this:
on_release: root.usename = root.gb()
I finally solved the issue, this's how we can read a text file and display it as label in another screen in kivy.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
f=open('test.txt','r')
t=f.readlines()
b=t[0]
f.close()
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
name:'xy'
id:loginscreen
BoxLayout:
orientation: "vertical"
Button:
text:'Execution button'
on_release: root.manager.current = "screen2"
<Screen2>:
name: "screen2"
FloatLayout:
Label:
text: root.username
Button:
text:'Back to menu'
size_hint:.3,.3
on_release: root.manager.current = "xy"
ScreenManager:
Screen1:
id:loginscreen
Screen2:
username: loginscreen.b
''')
class MyApp(App):
def build(self):
return root
r=MyApp()
r.run()

kivy adding attribute manager to a tabbedpanelitem

I'm trying to have a a screen inside a tabbed panels "space".
When i try to switch between screens, i get an AttributeError:
"AttributeError: 'TabbedTest' object has no attribute 'manager'"
I'm not sure how to add the screenmanager to the tabbedpanels attributes.
I'm unsure of how i create a reference to the tabbedpanel in the screenmanager or how i add the property.
Pythonfile
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.floatlayout import FloatLayout
class TabbedTest(TabbedPanel):
pass
class MainScreen(Screen):
pass
class Firstscreen(Screen):
pass
class myapp(App):
def build(self):
root = FloatLayout()
self.tabbedtest = TabbedTest()
root.add_widget(self.tabbedtest)
# Create the screen manager
self.sm = ScreenManager()
self.sm.add_widget(MainScreen(name='main'))
self.sm.add_widget(Firstscreen(name='first'))
root.add_widget(self.sm)
return root
if __name__ == '__main__':
myapp().run()
my.kv
<TabbedTest>
do_default_tab: False
TabbedPanelItem:
text:"test"
MainScreen:
Button:
text: 'first'
on_press: root.manager.current = 'first' #Problemarea
<Firstscreen>:
BoxLayout:
Label:
text:"first"
Button:
text: 'Back to main'
on_press: root.manager.current = 'main'
If you want the Screens inside the TabbedPanelItem, then you should put the ScreenManager inside the TabbedPanelItem. Here is a modified version of your kv that does that:
<TabbedTest>
do_default_tab: False
TabbedPanelItem:
text:"test"
ScreenManager:
id: manager # for easy access
MainScreen:
name: 'main'
Button:
text: 'first'
on_press: manager.current = 'first' # use manager id
Firstscreen:
name: 'first'
<Firstscreen>:
BoxLayout:
Label:
text:"first"
Button:
text: 'Back to main'
on_press: root.manager.current = 'main'
Then your build() method can be simply:
def build(self):
return TabbedTest()

Kivy Python: buttons and classes for multiple screens

I have a problem with my Kivy Python Code. I have 2 screens: 1st is to navigate to the second screen and on the 2nd screen there is a button to add text to a scrollview...navigating is working but it does not add any text to the scrollview...I think I need some help here! AttributeError: 'super' object has no attribute 'getattr'
import kivy
from kivy.app import App
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.screenmanager import ScreenManager, Screen
from kivy.clock import Clock, mainthread
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect
from kivy.lang import Builder
Builder.load_string("""
<MenuScreen>:
name: 'mainmenu'
BoxLayout:
spacing: 1
orientation: "vertical"
Label:
text: "MAIN MENU"
Button:
text: 'Go to Screen 2'
on_release:
root.manager.current = 'screen2'
root.manager.transition.direction = "left"
Button:
text: 'Quit'
on_release: root.manager.current = app.exit_software()
<Screen2>:
name: 'screen2'
BoxLayout:
spacing: 1
orientation: "vertical"
ScrollView:
id: scroll_view
always_overscroll: False
BoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Label:
id: label
text: "You can add some Text here by pressing the button"
size_hint: None, None
size: self.texture_size
Button:
text: 'Add text!'
size_hint_y: 0.1
on_release: app.add_text()
Button:
text: 'Back to main menu'
size_hint_y: 0.1
on_release:
root.manager.current = 'mainmenu'
root.manager.transition.direction = "right"
""")
# Declare both screens
class MenuScreen(Screen):
pass
class Screen2(Screen):
pass
class AddTextApp(App):
def __init__(self,**kwargs):
super().__init__(**kwargs)
def build(self):
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='mainmenu'))
sm.add_widget(Screen2(name='screen2'))
return sm
def add_text(self):
self.root.ids.label.text += f"Some new Text\n"
self.root.ids.scroll_view.scroll_y = 0
def exit_software(self):
App.get_running_app().stop()
if __name__ == '__main__':
AddTextApp().run()
Thank you very much in advance!
The error occurred because self.root.ids gets access to widgets located in the root widget of the main class. To access the secondary screen elements, you need to add it to the main class (in your case, in ScreenManager) and set its id. Also, you have a lot of imported excess, so that it is clearly visible, I advise you to use Pycharm or something like that.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
kv = """
<MenuScreen>:
name: 'mainmenu'
BoxLayout:
spacing: 1
orientation: "vertical"
Label:
text: "MAIN MENU"
Button:
text: 'Go to Screen 2'
on_release:
root.manager.current = 'screen2'
root.manager.transition.direction = "left"
Button:
text: 'Quit'
on_release: root.manager.current = app.exit_software()
<Screen2>:
name: 'screen2'
BoxLayout:
spacing: 1
orientation: "vertical"
ScrollView:
id: scroll_view
always_overscroll: False
BoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Label:
id: label
text: "You can add some Text here by pressing the button"
size_hint: None, None
size: self.texture_size
Button:
text: 'Add text!'
size_hint_y: 0.1
on_release: app.add_text()
Button:
text: 'Back to main menu'
size_hint_y: 0.1
on_release:
root.manager.current = 'mainmenu'
root.manager.transition.direction = "right"
ScreenManager:
MenuScreen:
id: menu_scr
Screen2:
id: scr_2
"""
class MenuScreen(Screen):
pass
class Screen2(Screen):
pass
class AddTextApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return Builder.load_string(kv)
def add_text(self):
self.root.ids.scr_2.ids.label.text += f"Some new Text\n"
self.root.ids.scr_2.ids.scroll_view.scroll_y = 0
#staticmethod
def exit_software():
App.get_running_app().stop()
if __name__ == '__main__':
AddTextApp().run()

Switching between kivy classes inside one screen

I'm looking for a way to change a part of a screen between 'DownPanel1' and 'DownPanel1' but I would like to avoide creating nex screen class 'ToAvoid'. Is it possible?
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
kv = '''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
SomeScreen:
ToAvoid:
<Menu#RelativeLayout>
id: main_menu
size_hint_x: None
width: 120
Button:
size_hint_y: None
pos: root.x, root.top - self.height
text: 'SomeScreen'
on_press: app.root.current = "SomeScreen"
<UpScreen>:
BoxLayout:
Button:
text: 'switch'
on_press: app.root.current = "ToAvoid"
<DownPanel1>:
Button:
text: 'DownPanel1'
#on_press:
<DownPanel2>:
Button:
text: 'DownPanel2'
#on_press:
<SomeScreen>:
name: 'SomeScreen'
BoxLayout:
orientation: 'horizontal'
Menu:
BoxLayout:
orientation: 'vertical'
UpScreen:
DownPanel1:
<ToAvoid>:
name: 'ToAvoid'
BoxLayout:
orientation: 'horizontal'
Menu:
BoxLayout:
orientation: 'vertical'
UpScreen:
DownPanel2:
'''
class DownPanel1(BoxLayout):
pass
class DownPanel2(BoxLayout):
pass
class UpScreen(Screen):
pass
class SomeScreen(Screen):
pass
class ToAvoid(Screen):
pass
class ScreenManagement(ScreenManager):
pass
sm = Builder.load_string(kv)
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
How about some inception? Just put another ScreenManager inside of the other.
Try this example:
from kivy.app import App
from kivy.lang import Builder
KV = """
ScreenManager:
Screen:
name: "1st"
Button:
text: "next"
on_release:
root.current = "2nd"
Screen:
name: "2nd"
BoxLayout:
Button:
text: "3rd to avoid"
on_release:
root.current = "3rd"
ScreenManager:
id: sm2
Screen:
name: "inner1"
Button:
text: "go to inner 2"
on_release:
sm2.current = "inner2"
Screen:
name: "inner2"
Label:
text: "This is inner 2!"
Screen:
name: "3rd"
Label:
text: "To Avoid!"
"""
class MyApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == "__main__":
MyApp().run()

Only one root object is allowed by .kv

I am doing an online kivy tutorial. Below is the code that I have written. It is exactly as was in the tutorial video.
But when I run the code I get the following error:
...
1:import FadeTransition kivy.uix.screenmanager.FadeTransition
2:
>> 3:ScreenManagement:
4: transition: FadeTransition()
5:
...
Only one root object is allowed by .kv
I think the error is with the FadeTransition because I have two instances-MainScreen and AnotherScreen but I do not know how to rectify it. And in the tutorial video the code ran properly. So why isn't it executing in my computer?
Below is the code that I have written
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
text: "Next Screen"
font_size: 50
on_release: root.app.current = "other"
<AnotherScreen>:
name: "other"
Button:
text: "Back Home"
font_size: 50
on_release: root.app.current = "main"
''')
class MainApp(App):
def build(self):
return presentation()
if __name__=="__main__":
MainApp().run()
Thanks in advance.
Try this code it might help a bit took a long time for me to figure it out:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = ('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
text: "Next Screen"
font_size: 50
on_release: root.app.current = "other"
<AnotherScreen>:
name: "other"
Button:
text: "Back Home"
font_size: 50
on_release: root.app.current = "main"
''')
class MainApp(App):
def build(self):
return Builder.load_string(presentation)
if __name__=="__main__":
MainApp().run()
I came across the exact issue as you while watching the same video. You will need to do this instead (assuming you want a fade transition):
Main.py file:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class ScreenManagement(ScreenManager): #here you are creating a screen manager called ScreenManagement
pass
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
presentation = Builder.load_file("Main2.kv") #telling the app which .kv file to use
class MainApp(App):
def build(self):
return presentation
runMain = MainApp()
runMain.run()
Now over to your Main2.kv file:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition() #telling the screen manager to use a fade transition
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main" #this name is what the screen manager uses to distinguish which screen to go to
Button:
text: "Go To Next Screen"
color:0,0,0,1
background_color: 1,1,1,1
size_hint: 1,0.10
pos:0,200
font_size: 30
on_release: app.root.current = "another" #the screen that the screen manager is told to go to
<AnotherScreen>:
name: "another"
Button:
text: "Go To Main Screen"
color:0,0,0,1
background_color: 1,1,1,1
size_hint: 1,0.10
pos:0,200
font_size: 30
on_release: app.root.current = "main"
Hope that helped.
In your kv file, you need to surround ScreenManagement class with "<" and ">" as shown in the example below.
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
class ScreenManagement(ScreenManager):
pass
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class MainApp(App):
def build(self):
return ScreenManagement()
if __name__ == "__main__":
MainApp().run()
main.kv
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
<ScreenManagement>:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
text: "Go To Next Screen"
color:0,0,0,1
background_color: 1,1,1,1
size_hint: 1,0.10
pos:0,200
font_size: 30
on_release: app.root.current = "another"
<AnotherScreen>:
name: "another"
Button:
text: "Go To Main Screen"
color:0,0,0,1
background_color: 1,1,1,1
size_hint: 1,0.10
pos:0,200
font_size: 30
on_release: app.root.current = "main"
Output

Categories

Resources