How can I access to the kivy data from MyScreenManager ? How can I access to Hellow or Timer data ? I cant use on_release: root.starttimer() in Hellow.
class Hellow(Screen):
pass
class Timer(Screen):
pass
class MyScreenManager(ScreenManager):
def starttimer(self):
#change text Hellow Button
root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
MyScreenManager:
transition: FadeTransition()
Hellow:
Timer:
<Hellow>:
AnchorLayout:
Button:
id: but
size_hint: None, None
size:300,100
text: 'make a foto'
font_size: 30
on_release: app.root.starttimer()
<Timer>:
name: 'Timer'
''')
class ScreenManagerApp(App):
def build(self):
print(self.ids)
return root_widget
if __name__ == '__main__':
ScreenManagerApp().run()
some text for stackoverflow (it says that I need to type more text),
Screen manager is only used to accept screen widgets if you try to add anything else like a button or label then it will throw an exception.
kivy.uix.screenmanager.ScreenManagerException: ScreenManager accepts only Screen widget.
Only one root object is allowed by .kv file In your case, you can access hello or Timer from each other.
<Hellow>:
name: 'hello'
...
Button:
id: but
...
on_release: root.parent.current = 'Timer'
<Timer>:
name: 'Timer'
Button:
text: "Take me back to hellow"
on_release: root.parent.current = 'hello'
but there could be another way too.
<Main>:
BoxLayout:
Button:
text: "Hello"
on_release: sm.current = 'Timer'
on_release: print(lbl.text)
Button:
text: "Timer"
on_release: sm.current = 'Hello'
ScreenManager:
id: sm
Screen:
name: hello
Label:
id: lbl
text: "I am hello"
Screen:
name: timer
Label:
text: "I am timer"
EDIT 1:
As you asked in your comment
class MyScreenManager(ScreenManager):
def __init__(self,**kwargs):
super(MyScreenManager,self).__init__(**kwargs)
def starttimer(self,event):
#print event.text
event.text = "changed text"
<Hellow>:
...
Button:
...
on_release: root.parent.starttimer(self)
Related
I'm trying to build an interface in python with Kivy. To do this, i want to follow this structure:
[ScreenManager#1] -> [Login Screen]
[ScreenManager#2] -> [All others screens]
My ScreenManager#1 is declared in my App function in python file. My ScreenManager#2 is initialised in a kv file. To simply the help that you can bring to me, i've joined the two in the code below.
my AllScreensScreenManager#2, need to have a template shared with all the other screens. I've gave an id to it and call this one with my button in my LoginScreen, like this was suggested here. But the switch is not working. What i'm doing wrong with it.
import kivy
kivy.require('2.1.0') # replace with your current kivy version !
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager,Screen
Builder.load_string('''
<AllScreens>:
id: second_manager
manager: scr_manager
orientation: "vertical"
BoxLayout:
ScreenManager:
id: scr_manager
transition: "left"
Welcome:
GenerateScreen:
ModifyScreen:
ConsultScreen:
LogoutScreen:
BoxLayout:
size_hint: 1, None
height: "40dp"
pos_hint: {"bottom": 0}
spacing: "5dp"
Button:
id: consult
text: "Consult"
on_press: root.manager.current("consult")
Button:
id: modify
text: "Modify"
on_press: root.manager.current("modify")
Button:
id: generate
text: "Generate"
on_press: root.manager.current("generate")
Button:
id: logout
text: "Logout"
on_press: root.manager.current("logout")
<LoginScreen>:
name: "login"
BoxLayout:
Label:
text: "Login"
Button:
text: "Connect"
on_release: second_manager.current("welcome")
<WelcomeScreen>:
name: "welcome"
BoxLayout:
Label:
text: "welcome"
<ConsultScreen>:
name: "consult"
BoxLayout:
Label:
text: "consult"
<GenerateScreen>:
name: "generate"
BoxLayout:
Label:
text: "password"
''')
class ScreenManagement(ScreenManager):
pass
class LoginScreen(Screen):
print("login screen")
pass
class WelcomeScreen(Screen):
pass
class AllScreens(ScreenManager):
pass
class ConsultScreen(Screen):
pass
class GenerateScreen(Screen):
pass
class MyApp(App):
def build(self):
sm = ScreenManagement()
sm.add_widget(LoginScreen(name="login"))
return sm
if __name__ == '__main__':
MyApp().run()
main.py:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.tabbedpanel import TabbedPanel
class Test(TabbedPanel):
pass
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("settings.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
settings.kv:
WindowManager:
MainWindow:
SecondWindow:
Test:
<MainWindow>:
name: "main"
GridLayout:
cols:2
Button:
text: "New Order"
on_release:
app.root.current = "tabs"
root.manager.transition.direction = "left"
Button:
text: "Basket"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
<Test>:
name: "test"
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
TabbedPanelItem:
text: 'first tab'
Label:
text: 'First tab content area'
TabbedPanelItem:
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
TabbedPanelItem:
text: 'tab3'
RstDocument:
text:
'\\n'.join(("Hello world", "-----------",
"You are in the third tab."))
I want a transition that starts with a button press that leads to a tabbed overlay, However the screenmanager doesnt accept the use of tabbedpanel
kivy.uix.screenmanager.ScreenManagerException: ScreenManager accepts only Screen widget.
How can I achieve this effect, I am new to kivy. I want one button press to go to a another normal screen while the other one to open a tabbed screen,
Just add a TabblePanel to one of your Screens.
<BlaBlaScreen>:
name: 'BlaBla'
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text: "something"
Just put your TabbedPanel in a Screen.
Good day. Use your screen manager to switch between each screen. The screen then contains your unique layout of whatever you placed in it. That could include a screen with tabs.
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()
I'm trying to make an app that will eventually be able to score cards. One problem I'm trying to solve is how to update the text of a button after pressing or updating it somehow. I'm newer to python/kivy. I've found a couple similar questions, dealing with functions and such, but none dealt with .kv files and separate windows. My code is below.
main.py
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class ScoreWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("mainkv.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
mainkv.kv
WindowManager:
MainWindow:
ScoreWindow:
<MainWindow>:
name: "main"
GridLayout:
cols: 1
Button:
text: "Quick Score"
on_release:
app.root.current = "score"
root.manager.transition.direction = "left"
<ScoreWindow>:
name: "score"
GridLayout:
cols: 7
Button:
name: "three"
text: "Press to Update"
on_release:
three.text = "Updated"
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: "Score"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Your Buttons can refer to themselves in kvlang using the self keyword. So just add another line that says self.text = 'foo' in the on_release: area of your Buttons.
I am using the Screen Manager to manage several different screens. One screen has two buttons that both lead to another screen, but depending on which button was pressed, I would like a label to display different text on the second screen. Here is my code:
.py
MY_GLOBAL = "test"
class ChooseProgScreen(Screen):
global MY_GLOBAL
def setTitle(self, newTitle):
MY_GLOBAL = newTitle
print(MY_GLOBAL)
class SwitchScreen(Screen):
global MY_GLOBAL
def getTitle(self):
return MY_GLOBAL
class ScreenManagement(ScreenManager):
pass
class MainApp(App):
def build(self):
presentation = Builder.load_file("kivy.kv")
return presentation
.kv
ScreenManagement:
transition: FadeTransition()
HomeScreen:
ChooseProgScreen:
SwitchScreen:
NewProgScreen:
<ChooseProgScreen>:
name: "chooseprog"
FloatLayout:
Button:
text: "test1"
on_release:
root.setTitle("test1")
app.root.current = "switch"
color: 1,1,1,1
font_size: 25
size_hint: 0.15,0.15
pos_hint: {"center_x":.1, "center_y":.9}
Button:
text: "test2"
on_release:
root.setTitle("test2")
app.root.current = "switch"
color: 1,1,1,1
font_size: 25
size_hint: 0.15,0.15
pos_hint: {"center_x":.3, "center_y":.9}
<SwitchScreen>:
name: "switch"
FloatLayout:
Label:
text: root.getTitle()
pos_hint: {"center_x":.1, "center_y":.1}
font_size: 25
In ChooseProgScreen in .kv, when the button is released, I call a method from the .py file that sets the global variable to a new screen and prints it. When you press one of the buttons, the print part works fine, and the global variable prints as the new string, but the SwitchScreen label still shows
"test"
and not
"test1" or "test2"
I think global variables is probably a terrible way of doing this, but I am at a loss for how else to do it using the Screen manager and the kivy language. If someone could help use global variables properly, or suggest a better way to do this, that would be greatly appreciated.
EDIT
Problem was that the screen only updated upon the first load. I added an update method to SwitchScreen:
def update(self):
self.ids.switchtitle.text = self.getTitle()
and updated the SwitchScreen in the .kv file:
<SwitchScreen>:
on_enter:
root.update()
Label:
id: switchtitle
text: root.getTitle()
pos_hint: {"center_x":.1, "center_y":.1}
font_size: 25
Solution
Define a class attribute, MY_GLOBAL of type StringProperty in your root widget, class ScreenManagement().
Update MY_GLOBAL in kv file.
Example
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class ChooseProgScreen(Screen):
pass
class SwitchScreen(Screen):
pass
class ScreenManagement(ScreenManager):
MY_GLOBAL = StringProperty('test')
class MainApp(App):
def build(self):
return Builder.load_file("kivy.kv")
if __name__ == "__main__":
MainApp().run()
kivy.kv
#:kivy 1.10.0
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
ChooseProgScreen:
SwitchScreen:
<ChooseProgScreen>:
name: "chooseprog"
FloatLayout:
Button:
text: "test1"
on_release:
root.manager.MY_GLOBAL = self.text
root.manager.current = "switch"
color: 1,1,1,1
font_size: 25
size_hint: 0.15,0.15
pos_hint: {"center_x":.1, "center_y":.9}
Button:
text: "test2"
on_release:
root.manager.MY_GLOBAL = self.text
root.manager.current = "switch"
color: 1,1,1,1
font_size: 25
size_hint: 0.15,0.15
pos_hint: {"center_x":.3, "center_y":.9}
<SwitchScreen>:
name: "switch"
FloatLayout:
Label:
text: root.manager.MY_GLOBAL
pos_hint: {"center_x":.1, "center_y":.1}
font_size: 25
Output
class ChooseProgScreen(Screen):
def setTitle(self, newTitle):
global MY_GLOBAL
MY_GLOBAL = newTitle
print(MY_GLOBAL)
That should resolve your issue. MY_GLOBAL would technically be available via self.MY_GLOBAL, instead you assigned it to a new variable under the method but didn't assign it to the global variable object.