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"
Related
I am trying to change the label of the button "Choose Activity" to "Schlafen" (in the Screen "DayWindow"), if the user clicks on the button "Schlafen" in the popup window.
My problem is that I dont know how to access the Screen "DayWindow" from the Popup-Class.
As you can see in the code, I tried to access it through the ScreenManager but than I get the Error: 'super' object has no attribute '__getattr__'
In another try I got the Error: Screen "day" does not exist
I would be very thankful for any help and tips.
My Pyhton File:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import runTouchApp
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
from datetime import date, timedelta
import json
class MenuWindow(Screen):
pass
class DayWindow(Screen):
null = ObjectProperty("Null")
def btn(self,index):
show_ActivityPopup()
def change_button():
scn = ScreenManager()
scn.ids.null.text = "Geschafft"
class WeekWindow(Screen):
pass
class MonthWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class ActivityPopup(FloatLayout):
def change_text(self):
DayWindow.change_button()
def show_ActivityPopup():
show = ActivityPopup()
ActivityPopupWindow = Popup(title="Activities", content=show, auto_dismiss=False)
ActivityPopupWindow.open()
kv = Builder.load_file("my.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()enter code here
My .kv - File
WindowManager:
MenuWindow:
DayWindow:
WeekWindow:
MonthWindow:
<MenuWindow>:
name: "menu"
GridLayout:
cols:1
Label:
text: "Time/MoodTracker"
Button:
text: "Day"
on_release:
app.root.current = "day"
root.manager.transition.direction ="left"
GridLayout:
cols: 2
Button:
text: "Weelky Overview"
on_release:
app.root.current = "week"
root.manager.transition.direction ="left"
Button:
text: "Monthly Overview"
on_release:
app.root.current = "month"
root.manager.transition.direction ="left"
<DayWindow>:
name: "day"
ScrollView:
GridLayout:
cols: 2
Label:
text: "0:00 - 0:30"
Button:
id: null
text: root.null
on_release:
root.btn(0)
Label:
text: "0:30 - 1:00"
id: Eins
Button:
text: "Choose Aviticity"
on_release: root.btn(1)
Label:
text: "1:00 - 1:30"
Button:
text: "Choose Aviticity"
on_release: root.btn(2)
Label:
text: "1:30 - 2:00"
Button:
text: "Choose Aviticity"
on_release: root.btn(3)
Label:
text: "2:00 - 2:30"
Button:
text: "Choose Aviticity"
on_release: root.btn(4)
<ActivityPopup>:
auto_dismiss: False
ScrollView:
GridLayout:
size_hint_y: None
cols:1
height: dp(600)
spacing: "10dp"
Button:
text: "Schlafen"
on_release:
root.change_text()
root.parent.parent.parent.dismiss()
Button:
text: "Frühstücken"
on_release:
root.parent.parent.parent.dismiss()
Button:
text: "Kochen"
Button:
text: "Lernen"
Button:
text: "Joggen"
<WeekWindow>:
name: "week"
Button:
text: "Back"
on_release:
app.root.current = "menu"
root.manager.transition.direction ="right"
<MonthWindow>:
name: "month"
Button:
text: "Back"
on_release:
app.root.current = "menu"
root.manager.transition.direction ="right"
A couple problems:
The code:
def change_button():
scn = ScreenManager()
scn.ids.null.text = "Geschafft"
is creating a new instance of ScreenManager, which has nothing to do with your App. So nothing that you do with scn will have any effect on your App.
And, in that same method, you are trying to access ids of the ScreenManager. Even if you were actually dealing with the WindowManager in your App, this would not work, because the WindowsManager has no defined ids.
The ids defined in your kv file are defined in the object that is the root of the rule where that id is defined. So, for example, the null id is defined in the ids of the DayWindow. The kivy documentation on this issue is confusing due to its multiple uses of the term root widget.
The fix is to just modify the change_text() method of the ActivityPopup class. Here is an updated version of that method, that should fix your problems:
class ActivityPopup(FloatLayout):
def change_text(self):
scn = App.get_running_app().root.get_screen('day')
scn.ids.null.text = "Geschafft"
I have problem with kivy in python.
I started tutorial at kivy website - pong in kivy. But there was a little problem - when i created a ball on screen and i wanted to move it - at the screen was created many balls - one ball for for one frame and they did not disappear.
I gave up and i started a 2nd tutorial on youtube - creating login screen. But i have the same problem with animation of screen change.
all you need to see is at the movie (youtube):
https://youtu.be/xXWq5XgQPnE
https://youtu.be/U6sKKLRD6Vk
there is the code of login screen :
python file:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("kvfile.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyMainApp().run()
kivy file:
#:kivy 2.0.0
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
GridLayout:
cols: 1
GridLayout:
cols: 2
Label:
text: "Name:"
TextInput:
id: uname
multilane: False
Label:
text: "Password:"
TextInput:
id: upass
multilane: False
Button:
text: "Log in"
on_release:
app.root.current = "second"
<SecondWindow>:
name: "second"
Button:
text: "Go back"
pos_hint: {"x": 0.3, "y": 0.2}
size_hint: 0.4, 0.2
on_release:
app.root.current = "main"
i have no idea what to do. any help?
You have to give your screens a name.
WindowManager:
MainWindow:
name: 'main'
SecondWindow:
name 'second'
And instead of calling app.root.current try calling root.manager.current
Here is some sample code that works on my computer...
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_string(
"""
WindowManager:
MainWindow:
name: 'main'
SecondWindow:
name: 'second'
<MainWindow>:
name: "main"
GridLayout:
cols: 1
GridLayout:
cols: 2
Label:
text: "Name:"
TextInput:
id: uname
multilane: False
Label:
text: "Password:"
TextInput:
id: upass
multilane: False
Button:
text: "Log in"
on_release:
root.manager.current = "second"
<SecondWindow>:
name: "second"
Button:
text: "Go back"
pos_hint: {"x": 0.3, "y": 0.2}
size_hint: 0.4, 0.2
on_release:
root.manager.current = "main"
"""
)
class MyMainApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyMainApp().run()
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"
I am trying to add an action bar on top in the first screen of my project. I tried using screenmanager widget and sending the action bar as it's children like how to manage/get both of the screens. At first I tried just adding the action bar code in root.widget in the first screen, but they are showing the class for this as an invalid class.
How to add both of them? Also I can't show the buttons from top to bottom even though I added orientation : 'vertical'
import kivy
kivy.require('1.10.1')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager,Screen,FadeTransition
class SomeLayout_GridLayout(Screen):
pass
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
pass
class ScreenManager(ScreenManager):
pass
root_widget = Builder.load_string('''
ScreenManager:
FirstScreen:
SecondScreen:
SomeLayout_GridLayout:
<FirstScreen>:
name: 'first'
<SomeLayout_GridLayout>:
cols: 1
rows: 2
row_force_default: True
rows_minimum: {0: ActionBar.height, 1: self.height - ActionBar.height}
SomeMenu_ActionBar:
id: ActionBar
<SomeMenu_ActionBar#ActionBar>:
ActionView:
id: ActionView
ActionGroup:
id: App_ActionGroup
mode: 'spinner'
text: 'App'
ActionButton:
text: 'Settings'
on_press: app.open_settings()
ActionButton:
text: 'Quit'
on_press: app.get_running_app().stop()
ActionGroup:
id: File_ActionGroup
mode: 'spinner'
text: 'File'
ActionButton:
text: 'Open'
ActionButton:
text: 'Save'
<HiddenIcon_ActionPrevious#ActionPrevious>:
title: app.title if app.title is not None else 'Action Previous'
with_previous: False
app_icon: ''
app_icon_width: 0
app_icon_height: 0
size_hint_x: None
width: len(self.title) * 10
<HiddenText_ActionPrevious#ActionPrevious>: #
with_previous: False
on_press: print(self)
title: ''
<Hidden_ActionPrevious#ActionPrevious>:
with_previous: False
on_press: print(self)
title: ''
size_hint: None, None
size: 0, 0
BoxLayout:
orientation: 'horizontal'
BoxLayout:
Button:
text: 'Crime Prediction'
font_size: 30
on_release: app.root.current = 'second'
Button:
text: 'Forum'
font_size: 30
on_release: app.root.current = 'second'
Button:
text: 'Probable Suspect'
font_size: 30
on_release: app.root.current = 'second'
<SecondScreen>:
name: 'second'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Predict Crime Nigga!'
font_size: 50
BoxLayout:`enter code here`
Button:
text: 'Back to Main Menu'
font_size: 30
on_release: app.root.current = 'first'
Button:
text: 'get random colour screen'
font_size: 30
on_release: app.root.current = 'first'
''')
class ScreenManagerApp(App):
def build(self):
return root_widget
ScreenManagerApp().run()
Kivy App with ActionBar & ScreenManager
Declare a root widget with inheritance of BoxLayout
Add ActionBar as child of root widget
Add ScreenManager as child of root widget, and with id: sm
Snippets
BoxLayout:
orientation: 'vertical'
ActionBar:
...
ScreenManager:
id: sm
FirstScreen:
SecondScreen:
Example
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
class WelcomeScreen(Screen):
pass
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
pass
class ScreenManager(ScreenManager):
pass
class CrimePrevention(BoxLayout):
pass
Builder.load_file("main.kv")
class TestApp(App):
title = 'Kivy ScreenManager & ActionBar Demo'
def build(self):
return CrimePrevention()
if __name__ == '__main__':
TestApp().run()
main.kv
#:kivy 1.11.0
#:import sp kivy.metrics.sp
#:import dp kivy.metrics.dp
<CrimePrevention>:
orientation: 'vertical'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
# source: 'data/background.png'
SomeMenu_ActionBar:
id: ActionBar
ScreenManager:
id: sm
WelcomeScreen:
FirstScreen:
SecondScreen:
<SomeMenu_ActionBar#ActionBar>:
ActionView:
id: ActionView
HiddenIcon_ActionPrevious:
ActionGroup:
id: App_ActionGroup
mode: 'spinner'
text: 'Jump to Screen'
ActionButton:
text: 'Crime Prediction'
on_release: app.root.ids.sm.current = 'second'
ActionButton:
text: 'Forum'
on_release: app.root.ids.sm.current = 'second'
ActionButton:
text: 'Probable Suspect'
on_release: app.root.ids.sm.current = 'second'
ActionGroup:
id: App_ActionGroup
mode: 'spinner'
text: 'App'
ActionButton:
text: 'Settings'
on_press: app.open_settings()
ActionButton:
text: 'Quit'
on_press: app.get_running_app().stop()
ActionGroup:
id: File_ActionGroup
mode: 'spinner'
text: 'File'
ActionButton:
text: 'Open'
ActionButton:
text: 'Save'
<HiddenIcon_ActionPrevious#ActionPrevious>:
title: '' # app.title if app.title is not None else 'Action Previous'
with_previous: False
app_icon: ''
app_icon_width: 0
app_icon_height: 0
size_hint_x: None
width: len(self.title) * 10
<WelcomeScreen>:
name: 'welcome'
Label:
text: 'Welcome Screen'
font_size: sp(50)
<FirstScreen>:
name: 'first'
Label:
text: 'First Screen'
<SecondScreen>:
name: 'second'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Predict Crime'
font_size: 50
BoxLayout:
Button:
text: 'Back to Main Menu'
font_size: 30
on_release: app.root.ids.sm.current = 'first'
Button:
text: 'get random colour screen'
font_size: 30
on_release: app.root.ids.sm.current = 'first'
Output
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'