I am learning Kivy, but I do not kown how to change a screen and running a funtion at the same time.
Where should I declare my funtion so the button have access to the code and can run the function?
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
screen_helper = """
ScreenManager:
MenuScreen:
FunctionScreen:
<MenuScreen>:
name: 'menu'
MDRectangleFlatButton:
text: 'Function'
pos_hint: {'center_x':0.5,'center_y':0.5}
on_press: root.manager.current = 'function screen'
<FunctionScreen>:
name: 'function screen'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class FunctionScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(FunctionScreen(name='function'))
class DemoApp(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
# def funtion(self):
# do stuff and then go to menu screen
DemoApp().run()
Should I try maybe, add the on_opress atribute in the build function?
Can you guys help me?
There are several convenient places to place the function(). One is in the MenuScreen, and in that case, it would be referenced in the kv files as:
root.function()
Another convenient place is in the DemoApp, and in that case, the reference would be:
app.function()
So, here is a version of your code tht puts the function() in the App:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
screen_helper = """
ScreenManager:
MenuScreen:
FunctionScreen:
<MenuScreen>:
name: 'menu'
MDRectangleFlatButton:
text: 'Function'
pos_hint: {'center_x':0.5,'center_y':0.5}
on_press:
root.manager.current = 'function screen'
app.function()
<FunctionScreen>:
name: 'function screen'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class FunctionScreen(Screen):
pass
class DemoApp(MDApp):
def build(self):
sm = Builder.load_string(screen_helper)
return sm
def function(self):
# do stuff and then go to menu screen
print('in function')
DemoApp().run()
Note that the lines of your code that built a ScreenManager have been deleted as they are unnecessary.
Related
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()
i cannot remove widget using the screen with kivy python, i dont know why it just does not do anything
the code was suppose to remove textinput with id:name on the first screen but it just does not do anything and no error message.
here is all of the code it is tested on python 3.7.4, kivy 1.11.1 on window.
module_media_player.py
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.core.audio import SoundLoader
from kivy.uix.videoplayer import VideoPlayer
from kivy.uix.screenmanager import ScreenManager,Screen
class Player(Screen):
def press(self):
self.ids.name.text = 'nice'
def remove(self):
self.remove_widget(self.ids.name)
class MediaPlayer(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('my.kv')
class GoodApp(App):
def build(self):
return kv
if __name__ == '__main__':
GoodApp().run()
my.kv
WindowManager:
Player:
MediaPlayer:
<Player>:
name:"player"
BoxLayout:
orientation:"vertical"
size:root.width,root.height
cols:2
TextInput:
id:name
multiline:False
text:"first"
font_size:12
size_hint_y:0.3
Button:
text:"click me"
on_press:root.remove()
Button:
text:"next window"
font_size:14
size_hint_y:0.7
on_release:
app.root.current = "mediaplayer"
root.manager.transition.direction = "left"
<MediaPlayer>:
name:"mediaplayer"
BoxLayout:
orientation:"vertical"
size:root.width,root.height
Label:
text:"second"
font_size:12
Button:
text:"previous window"
font_size:14
on_release:
app.root.current = "player"
root.manager.transition.direction = "right"
Your code:
def remove(self):
self.remove_widget(self.ids.name)
is trying to remove the TextInput from the Player Screen, but that Textinput is not a child of Player. It is actually a child of the BoxLayout. You can fix this by modifying your remove() method:
def remove(self):
textinput = self.ids.name
textinput.parent.remove_widget(textinput) # remove widget from its parent
I have a simple problem which keeps me busy in the last days.
In Kivy I have two Windows.
FirstWindow has a method update(), which is triggered by a button press.
On SecondWindow I have only one button, which sends me back to FirsWindow, but I want it to trigger the update() method from FirstWindow and change the label, just like the "update label" button does on FirstWindow, without previously pressing the "update label" button.
Any help, please?
file.py
from kivy.app import App
from kivy.properties import ObjectProperty, ListProperty, ReferenceListProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class FirstWindow(Screen):
my_button = ObjectProperty(None)
my_label = ObjectProperty(None)
def update(self):
self.my_label.text = 'UPDATED'
class SecondWindow(Screen):
def go_first(self):
FirstWindow().update()
class WindowManager(ScreenManager):
pass
class MyTestApp(App):
def build(self):
return Builder.load_file('my_test.kv')
MyTestApp().run()
my_test.kv
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
my_label: my_label_id
BoxLayout:
Label:
id: my_label_id
text:"Label"
font_size:self.width / 5
BoxLayout:
orientation: "vertical"
Button:
text: "next screen"
on_press: root.manager.current = 'second'
Button:
text: "update label"
on_press: root.update()
<SecondWindow>:
name:"second"
Button:
text: "go back and update"
on_press:
root.manager.current = 'first'
root.go_first()
I think critical is this method, whitch needs to be remake, but I have no idea how
def go_first(self):
FirstWindow().update()
You can't directly access another screen which is defined as another class. First, you have to access the ScreenManager i.e. Parent class and then from it get the screen FirstScreen
So the go_first function in your code will look like this:
def go_first(self):
self.parent.get_screen('first').update()
EDIT:
Here's full code:
main.py:
from kivy.app import App
from kivy.properties import ObjectProperty, ListProperty, ReferenceListProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class FirstWindow(Screen):
my_button = ObjectProperty(None)
my_label = ObjectProperty(None)
def update(self):
self.my_label.text = 'UPDATED'
class SecondWindow(Screen):
def go_first(self):
self.parent.get_screen('first').update()
class WindowManager(ScreenManager):
pass
class MyTestApp(App):
def build(self):
return Builder.load_file('my.kv')
MyTestApp().run()
my.kv:
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
my_label: my_label_id
BoxLayout:
Label:
id: my_label_id
text:"Label"
font_size:self.width / 5
BoxLayout:
orientation: "vertical"
Button:
text: "next screen"
on_press: root.manager.current = 'second'
Button:
text: "update label"
on_press: root.update()
<SecondWindow>:
name:"second"
Button:
text: "go back and update"
on_press:
root.manager.current = 'first'
root.go_first()
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'
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