Accessing function in other kivy sceens - python

I am trying to figure out how to ensure my the calculations function is available as a global function able to be used no matter where in the app it is called.
Currently I am getting:
AttributeError: 'InputScreen' object has no attribute 'calculations'
main.py
import math
import kivy
from kivy.app import App
from decimal import Decimal, ROUND_UP
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput
class ScreenSwitch(ScreenManager):
pass
class DisplayScreen(Screen):
pass
class InputScreen(Screen):
pass
class Calculations():
def calculations(self):
org_amount = self.ids.orgamount.text
org_1 = int(self.ids.orgtip.text)
total = org_amount * org_1
class testApp(App):
def build(self):
self.title= "test1 v:1"
testApp().run()
test.kv
ScreenSwitch:
DisplayScreen:
InputScreen:
<DisplayScreen>:
name: "display"
GridLayout:
rows:1
cols:1
Button:
id: Displaymanualentry
text: "Manual Entry"
on_release: app.root.current = "input"
<InputScreen>:
name: "input"
GridLayout:
rows: 1
cols: 2
Button:
id: Inputreset
text: "Reset"
on_release: app.root.current= "display"
Button:
id: Inputsubmit
text: "Submit"
on_press: root.calculations()
on_release: app.root.current = "display"

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 button calls method of another class

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

Why popup dismiss method causes an error? (python kivymd)

I'm trying to make a app. On button click on the bottom right of the screen there appears a dialog window(popup). On "Done" click the popup window is expected to close (close_dialog method), but for some reason there appears AttributeError:
AttributeError: 'grudget4App' object has no attribute 'close_dialog'
Could you please tell me why the code doesn't work and how to fix it. Thanks.
.py code:
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.textfield import MDTextField
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.list import TwoLineAvatarListItem
Window.size = (288, 511)
class DialogContent(BoxLayout):
pass
class Container(Screen):
dialog = None
def show_dialog(self, *args):
'''
Create group creation popup
'''
if not self.dialog:
self.dialog = MDDialog(
title="Create new group",
type="custom",
content_cls=DialogContent(),
auto_dismiss=False
)
self.dialog.open()
def close_dialog(self, *args):
'''
Close popup on Done click
'''
self.dialog.dismiss()
class grudget4App(MDApp):
def build(self):
container = Container()
return container
if __name__ == '__main__':
grudget4App().run()
.kv code:
<DialogContent>:
textfield: textfield
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField:
id: textfield
hint_text: "Group name"
MDFlatButton:
id: btn1
text: "Done"
text_color: self.theme_cls.primary_color
on_release: app.close_dialog()
<Container>:
MDFloatingActionButton:
pos_hint: {'right': 0.95, 'y': 0.05}
icon: "icon.png"
theme_text_color: "Custom"
text_color: app.theme_cls.primary_color
on_release:
root.show_dialog()
Screen:
NavigationLayout:
ScreenManager:
Screen:
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'Demo Application'
left_action_items: [["menu", lambda x: nav_drawer.toggle_nav_drawer()]]
elevation:10
Widget:
MDNavigationDrawer:
id: nav_drawer
The method on_release: app.close_dialog() refers to your grudget4App class, but you want to call the method inside your Container class.
So we need to get the right screen inside your app. Since Container is the only screen there, and also the root, you can use:
on_release: app.root.close_dialog()

How can I add an amount of widgets in the kv file based on user input?

I'm trying to make a program that puts x amount of TextInputs based on the user's input. I can do that in the py file, but how do I do this in the kv file? I also need to be able to reference these TextInputs later on.
This is what I have so far:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.textinput import TextInput
class GetCount(Screen):
count_input = ObjectProperty(None)
def next(self):
# Setup next screen
text_inputs = [TextInput(multiline=False) for i in range(int(self.count_input.text))]
for text_input in text_inputs:
self.manager.ids.get_input.ids.grid.add_widget(text_input)
# Switch to next screen
self.manager.current = "get_input"
class GetInput(Screen):
pass
kv_file = Builder.load_string("""
ScreenManager:
GetCount:
name: "get_count"
id: get_count
GetInput:
name: "get_input"
id: get_input
<GetCount>:
count_input: count_input
FloatLayout:
Label:
text: "count"
size_hint: 1, 0.05
pos_hint: {"top":0.9}
TextInput:
id: count_input
size_hint: 0.8, 0.05
pos_hint: {"top":0.7, "x":0.1}
multiline: False
Button:
text: "Next"
on_release: root.next()
size_hint: 0.8, 0.05
pos_hint: {"top":0.5, "x":0.1}
<GetInput>:
FloatLayout:
GridLayout:
id: grid
cols: 1
""")
class MainApp(App):
def build(self):
return kv_file
if __name__ == "__main__":
app = MainApp()
app.run()
The problem is, the TextInputs are being added and created by the py code, how can I create the widget in kv and then add it in py?

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