problem with python kivy - screen refresh issues - python

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()

Related

How can I change the text of a button in another screen when I am in a popup-window?

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"

Recup input value through screen manager kivy

I want to catch a value from my first screen into my thirdscreen.
In the first, I write my name in an input field.
I go to the next window.
And I try to show my name in this last window.
So I share the code with you and I hope I will find an issue.
Python code :
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
#define ou different screens
class FirstWindow(Screen):
def envoyer(self):
name = self.ids.nom_input.text
self.ids.my_name.text = name
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
#PROBLEM HERE
def on_press(self):
self.ids.recup_infos.text = self.root.get_screen('FirstWindow').ids.my_name.text
class WindowManager(ScreenManager):
pass
class MonWidget(Widget):
pass
kv = Builder.load_file('new_window.kv')
class AwesomeApp(App):
def build(self):
Window.clearcolor = (0,0,0,0)
return kv
if __name__ == '__main__':
AwesomeApp().run()
My KV CODE :
WindowManager:
FirstWindow:
SecondWindow:
ThirdWindow:
<FirstWindow>:
name: "romain"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
id: my_name
text: "Entrez votre nom"
font_size: 32
TextInput:
id: nom_input
multiline: False
size_hint: (1, .5)
Button:
text: "Next screen"
font_size: 32
on_press: root.envoyer()
on_release:
app.root.current = "Mickael"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "Mickael"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Entre votre ville"
font_size: 32
TextInput:
id: ville_input
multiline: False
size_hint: (1, .5)
Button:
text: "Vérifier les infos"
font_size: 32
on_release:
app.root.current = "foncier"
root.manager.transition.direction = "left"
Button:
text: "go back first screen"
font_size: 32
on_release:
app.root.current = "romain"
root.manager.transition.direction = "right"
<ThirdWindow>:
name: "foncier"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Verifier : "
font_size: 32
Label:
id: recup_infos
text: ""
font_size: 32
color: 'white'
Button:
text: "On press"
font_size: 32
#Problem HERE
on_press: root.on_press()
Button:
text: "Précedent"
font_size: 32
on_release:
app.root.current = "Mickael"
root.manager.transition.direction = "right"
Could you help me ?
Thank you
Romain
In your on_press method:
def on_press(self):
self.ids.recup_infos.text = self.root.get_screen('FirstWindow').ids.my_name.text
self.root.get_screen('FirstWindow').ids.my_name.text isn't the correct way to get access to widgets outside of the class that you are in right now, or in this situation, screen. The correct way is to use the App.get_running_app() method:
self.ids.recup_infos.text = App.get_running_app().root.ids.First.ids.my_name.text
But before doing that, you have to give ids to the screens of your app, so that the First argument of the method demonstrated above actually makes sense:
WindowManager:
FirstWindow:
id: First
# "First" is the id of the FirstWindow class
# which can also explain why there was a "First" arg
# inside "App.get_running_app().root.ids.First.ids.my_name.text"
SecondWindow:
id: Second
ThirdWindow:
id: Third
Still confused to why this works? Let's divide the attributes of App.get_running_app().root.ids.First.ids.my_name.text into 3 parts:
App.get_running_app(): this method returns the location of your running App class, in this case AwesomeApp. This also acts as self if you were to get the variable inside the App object itself
.root.ids.First: if you read the Kivy documentation, or just simply watched Kivy course videos online, carefully, you should know that self.root.ids inside the App object returns a list of ids of the widgets inside your root widget. In this case, App.get_running_app().root.ids is doing the same thing here, and your screens are passed in the ScreenManager root widget, hence make First an available attribute in App.get_running_app().root.ids
.ids.my_name.text: same as above, App.get_running_app().root.ids.First acts the same as self if you were to run it in your FirstWindow class, which gives you the opportunity to get access to variables outside of your working classes/screens

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"

Kivy Taking user input from textinput and setting the text as a label

I have seen plenty of very similar questions asked, and none of the answers seem to work. I stripped a program to it's very basics and it still doesn't seem to work, here's the code:
.kv file
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: 'first'
GridLayout:
cols: 1
size: root.size
GridLayout:
cols: 2
Label:
text: 'Put some text'
TextInput:
id: item
Button:
on_release: app.root.current = 'second'
<SecondWindow>:
name: 'second'
BoxLayout:
orientation: 'vertical'
Label:
id: bi
text: root.manager.get_screen('first').ids.item.text
The .py file is very basic, no extra info that could conflict the program. So when I enter text into the label, it returns an empty string on the Second Screen. Can anyone help?
Your screen manager looks unfamiliar with me, try this:
main.kv
<RootWidget>:
manager: manager
ScreenManager:
id: manager
pos_hint: {'top': 0.9}
Screen:
name: 'Screen 1'
TextInput:
id: input1
text: 'Type Here'
size_hint: 0.2,0.1
pos_hint: {'center_x':0.5,'center_y':0.6}
Button:
text: 'Move to screen 2'
size_hint: 0.2,0.1
pos_hint: {'center_x':0.5,'center_y':0.4}
on_release: app.tmb1()
Screen:
name: 'Screen 2'
TextInput:
id: input2
text: 'Screen 2'
size_hint: 0.2,0.1
pos_hint: {'center_x':0.5,'center_y':0.6}
Button:
text: 'Move to screen 1'
size_hint: 0.2,0.1
pos_hint: {'center_x':0.5,'center_y':0.4}
on_release: app.tmb2()
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, ObjectProperty
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
class RootWidget(FloatLayout):
manager = ObjectProperty()
class MainApp(App):
def build(self):
return RootWidget()
def tmb1(self):
self.root.ids['input2'].text=self.root.ids['input1'].text
self.root.manager.current='Screen 2'
def tmb2(self):
self.root.ids['input1'].text=self.root.ids['input2'].text
self.root.manager.current='Screen 1'
if __name__ == '__main__':
MainApp().run()

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"

Categories