Can you make global variables available in every screen? - python

I would like to use global variables that once calculated with a method on the Input Screen, can be used to display information on the display screen but also be imported to the Display Screen to finish other calculations that will displayed on the screen.
My current global variables will be created on the Input Screen calculations() and Display Screen display fill. Also, the global variables will be used in an on_enter function in more calculations.
I am also having an issue getting the camera to capture the image. It displays on the screen but I dont get a saved picture.
main.py
import kivy
import time
from kivy.app import App
from kivy.lang import Builder
from kivy.metrics import dp, sp
from kivy.uix.button import Button
from kivy.uix.camera import Camera
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.screenmanager import Screen, ScreenManager
Builder.load_file('tipBot.kv')
Builder.load_file('camera.kv')
Builder.load_file('input.kv')
#global variables
amount = ''
tip = ''
total = ''
split= ''
class CameraScreen(Screen):
pass
class DisplayScreen(Screen):
def displayfill(self):
input1 = self.manager.get_screen("input_screen")
amount = input1.ids.orgamount.text
tip_3 = input1.ids.orgtip.text
self.finalamount.ids.text = "Tip: {tip} Tip %: {tip_3} Total: {total}"
class InputScreen(Screen):
def calculations(self):
org_amount = self.ids.orgamount.text
org_tip = int(self.ids.orgtip.text)
org_split = int(self.ids.split1.text)
tip1 = org_tip/100
tip = round(tip1*float(org_amount), 2)
total = round(tip + float(org_amount), 2)
total_str = str(int(total))
total_x = total_str[-1]
if org_split == 0:
split = org_split
else:
split = round(total/org_split, 2)
class SettingScreen(Screen):
pass
class ScreenSwitch(ScreenManager):
pass
class tipBotApp(App):
def build(self):
self.title = "tibBot version: 1"
return ScreenSwitch()
def capture(self, *args):
cam = self.root.ids.camera
timestamp = time.strftime("%Y%m%d_%H%M%S")
cam.export_to_png("Image.png")
tipBotApp().run()
camera.kv
<CameraScreen>:
GridLayout:
cols: 1
Camera:
id: camera
BoxLayout:
cols: 2
rows: 1
Button:
id: camerainput
text: "CAPTURE"
on_press: app.capture
Button:
id: cameramanual
text: "MANUAL ENTRY"
pos: dp(600), dp(400)
on_press: app.root.current = "input_screen"
input.kv
<InputScreen>:
GridLayout:
cols: 1
Label:
text: "PLEASE ENTER INFORMATION"
bold: True
font_size: '35sp'
GridLayout:
cols: 2
rows: 6
Label:
text: "Enter Original Amount of Bill:"
bold: True
font_size: '30sp'
TextInput:
id: orgamount
hint_text: 'Enter number w/ 2 decimal places'
hint_text_color: 'gray'
multiline: False
font_size: '30sp'
Label:
text: 'Enter tip amount as whole number:'
bold: True
font_size: '30sp'
TextInput:
id: orgtip
hint_text_color: 'gray'
hint_text: 'Enter a whole number'
multiline: False
font_size: '30sp'
Label:
text: 'Number splitting bill:'
bold: True
font_size: '30sp'
TextInput:
id: split1
hint_text: 'Enter # splitting bill'
hint_text_color: 'gray'
font_size: '30sp'
multiline: False
GridLayout:
cols: 3
Button:
id: inputsubmit
text: 'SUBMIT'
on_press: root.calculations()
on_press: app.root.current = "display_screen"
Button:
id: inputreset
text: 'RESET'
Button:
id: inputsetting
text: 'SETTINGS'
tipBot.kv
<ScreenSwitch>:
CameraScreen:
name: 'camera_screen'
id: camera_screen
DisplayScreen:
name: 'display_screen'
id: display_screen
InputScreen:
name: 'input_screen'
id: input_screen
SettingScreen:
name: 'setting_screen'
id: setting_screen
display.kv
<DisplayScreen>:
Gridlayout:
cols: 1
Label:
text: "Original Amount Tip Information"
bold: True
font_size: '40sp'
TextInput:
id: finalamount
bold: True
font_size: '40sp'
Label:
text: "Rounded to Nearest Dollar"
bold: True
font_size: '40sp'
TextInput:
id: onedollaramount
bold: True
font_size: '40sp'

You are not actually accessing the global variables. If you create a variable with the same name as a global variable in a method, that variable will be a local variable that hides the global variable. For example, in your displayfill() method, there is a local variable named amount that is not related to the global variable with the same name. The fix is to add the line:
global amount
at the start of the displayfill() method.

Related

Save the data of the screen using Kivy library

I have been writing a script to develop an app that calculates the results of Mahjong game.
I have created multiple screens to enter the players name and enter the score etc. in one of the screen I am entering the score and it is not getting saved. As soon as I move to other screen, the score data is lost. How can i save the score in the screen?
.py file looks like below
Window.size = (360, 600)
class MainScreen(Screen):
pass
class Player_Screen(Screen):
#pass
#def callback(self, text):
#self.ids.textbox.text = text
class ScreenManagement(ScreenManager):
shared_data = StringProperty("")
Mahjong = Builder.load_file('trial_app.kv') # Specifying location of kv file
class MainApp(App):
def build(self):
return Mahjong
if __name__ == "__main__":
MainApp().run()
my .kv file looks like below
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import App kivy.app.App
ScreenManagement:
#title: title # so I can use it in the .py file
#score:score # same here
transition: FadeTransition()
MainScreen:
id: title
Player_Screen:
id: Players
name: 'Players'
<MainScreen>:
name: "main"
canvas.before:
Color:
rgba: 0.2, 0.5, 1, 0.5
Rectangle:
pos: self.pos
size: self.size
GridLayout:
cols : 1
Button:
text: "Mahjong"
background_normal:'Mahjong.JPG'
Button:
text: "Let's Play"
on_release: app.root.current = "Contents"
<Player_Screen>:
f_username: Name
BoxLayout:
orientation: 'vertical'
id:f_username
TextInput:
id: Name
hint_text:'Enter Player1'
on_text: root.manager.shared_data = self.text #root.player_name()
TextInput:
id: Name
hint_text:'Enter Player2'
on_text: root.manager.shared_data = self.text
TextInput:
id: Name
hint_text:'Enter Player3'
on_text: root.manager.shared_data = self.text
TextInput:
id: Name
hint_text:'Enter Player4'
on_text: root.manager.shared_data = self.text
Button:
text: 'Back'
on_press: self.background_color = 0,0,0,1
on_release: root.manager.current = 'Contents'
Button:
text: 'Next'
#on_press: root.callback(self.text)
on_press: root.save_data()
on_release: root.manager.current = 'Score'
First of all kindly note that your last edited code is not a reproducible one. It's sometimes quite essential to be such one.
However if I got you right, you want to share or use the entered data in the input fields somewhere in your code as long as the application is running. If that's the requirement, you can do it in multiple ways. Here's a such one:
To store all data centrally in shared_data make it a DictProperty.
class ScreenManagement(ScreenManager):
shared_data = DictProperty(rebind = True)
# rebind is necessary for nested access in kvlang.
Feed the data in the input fields using different keys as follows,
<Player_Screen>:
f_username: Name
BoxLayout:
orientation: 'vertical'
id:f_username
TextInput:
id: Name
hint_text:'Enter Player1'
on_text: root.manager.shared_data["player1"] = self.text
TextInput:
id: Name
hint_text:'Enter Player2'
on_text: root.manager.shared_data["player2"] = self.text
...
Once they are stored, you can access them anywhere from the ScreenManagement instance of your GUI (which also happens to be the root). I've added another screen to demonstrate that.
class PlayerNameScreen(Screen):
pass
Now in kvlang for that screen,
...
ScreenManagement:
#title: title # so I can use it in the .py file
#score:score # same here
transition: FadeTransition()
MainScreen:
id: title
Player_Screen:
id: Players
name: 'Players'
PlayerNameScreen:
name: "player_names"
<PlayerNameScreen>:
Label:
text: "\\n".join(f"{player} : {name}" for player, name in root.manager.shared_data.items())
Button:
size_hint: None, None
size: "100dp", "50dp"
pos_hint: {"center_x" : 0.5, "center_y" : 0.2}
text: "Back"
on_release: root.manager.current = "Players"

How can I verify that my textfield is empty?

def check_full_name(self):
toast("You have to enter your full name to use the app correctly ! ")
MDTextFieldRound:
id:user_app
hint_text: "Full Name"
size_hint_x: None
size_hint_y: 0.08
width: 247
font_size: 18
pos_hint: {'center_x':0.5, 'center_y':0.62}
on_release: app.check_full_name() if user_app.text == '' else app.root.current = "accueil"
I don't know why it doesn't work, I want that when a field is empty calls my check_full_name function.Thanks for answering
According to your question, this should fix your problem:
.py file
from kivymd.app import MDApp
from kivymd.toast import toast
class PyApp(MDApp):
def on_start(self):
if self.root.ids.user_app.text == '':
self.check_full_name()
else:
self.root.ids.user_app.current = "accueil"
def check_full_name(self):
toast("You have to enter your full name to use the app correctly ! ")
PyApp().run()
.kv file
FloatLayout:
MDTextFieldRound:
id:user_app
hint_text: "Full Name"
size_hint_x: None
size_hint_y: 0.08
width: 247
font_size: 18
pos_hint: {'center_x':0.5, 'center_y':0.62}
on_text_validate: app.on_start()
class SplashScreenApp(MDApp):
dialog = None
def build(self):
dialog = None
self.title = "ReviewinApp"
global sm
sm = ScreenManager()
sm.add_widget(Builder.load_file("splash.kv"))
sm.add_widget(Builder.load_file("accueil.kv"))
sm.add_widget(Builder.load_file('conditions.kv'))
sm.add_widget(Builder.load_file("register.kv"))
sm.add_widget(Builder.load_file("faq.kv"))
sm.add_widget(Builder.load_file("login.kv"))
sm.add_widget(Builder.load_file("User2.kv"))
self.theme_cls.theme_style = "Light"
return sm
def on_start(self):
if self.root.ids.user_app.text == ' ':
toast("Please register correctly")
else:
toast("It's okay")
```
MDFillRoundFlatButton:
text: "Finish !"
font_size: "20sp"
font_name: "OpenSans"
pos_hint: {'center_x':0.5, 'center_y':0.07}
halign: 'center'
theme_text_color:'Custom'
text_color: 255/255, 255/255, 255/255, 1
size_hint: (0.58, 0.06)
md_bg_color: 62/255, 216/255, 133/255, 1
background_normal:''
on_press: app.on_start()
```
The python file and the kivy files are on different pages. One with extension .kv and one with .py

how to redirect from one page two other page with an if statement

I want this program to read information from the database and if it was correct, go to the main page of the program
Otherwise say that the information is wrong
how to redirect from one page two other page with an if statement
if user input and password was True by pressing button go to home
otherwise print password or user wrong
It is supposed to read data from the database
.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.lang import Builder
from kivy import Config
Builder.load_file("kivy.kv")
class AddUser(Screen):
def changeScreen(self):
self.ids.Gotologin.on_press = self.manager.transition.direction = 'up'
def getUserInfo(self):
name = self.ids.addusername.text
paswd = self.ids.addpassword.text
phone = self.ids.addphone.text
gmail = self.ids.addgmial.text
if len(paswd) == 0 and len(name) == 0:
self.ids.passwordles.text = "Enter your name & Password !"
elif len(paswd) <= 0:
self.ids.passwordles.text = "Add a Pssword !"
elif len(paswd) <= 6:
self.ids.passwordles.text = "Password is too small"
elif len(name) <= 0:
self.ids.passwordles.text = "Enter your Name !"
class Home(Screen):
def add(self):
name = self.ids.Name.text
number = self.ids.Number.text
ID = self.ids.Id.text
Buy = self.ids.Buy.text
sale = self.ids.Sale.text
ex_date = self.ids.exdate.text
usage = self.ids.Usage.text
medicine = self.ids.Medicine.text
Category = self.ids.Catigory.text
class LogIn(Screen):
def get(self):
cr.execute("SELECT * FROM login")
log = cr.fetchall()
user = self.ids.username.text
paswd = self.ids.password.text
Screen_Manager = ScreenManager()
Screen_Manager.add_widget(AddUser(name="Adduser"))
Screen_Manager.add_widget(LogIn(name="Login"))
Screen_Manager.add_widget(Home(name="Home"))
# main class to run application
class MainApp(App):
def build(self):
return Screen_Manager
if __name__ == "__main__":
MainApp().run()
.kv
<AddUser>:
BoxLayout:
canvas.before:
Color:
rgba:0,0,1,1
Rectangle:
size:self.size
pos:self.pos
orientation:"vertical"
BoxLayout:
Label:
id:passwordles
text:""
BoxLayout:
orientation:'vertical'
BoxLayout:
Label:
size_hint_x:.22
text:""
Label:
text:"User Name *"
Label:
text:"Password *"
Label:
text:"Phone Number"
Label:
text:"Gmail"
Label:
size_hint_x:.22
BoxLayout:
Label:
size_hint_x:.22
text:""
TextInput:
id:addusername
size_hint_y:.5
hint_text:"User Name"
TextInput:
id:addpassword
size_hint_y:.5
password:True
hint_text:"Password"
TextInput:
id:addphone
size_hint_y:.5
hint_text:"Phone Number"
TextInput:
id:addgmial
size_hint_y:.5
hint_text:"Gmail"
Label:
size_hint_x:.22
BoxLayout:
Label:
text:""
Button:
id:Gotologin
radius: 100, 100, 100, 100
font_name:"fonts/MTCORSVA.TTF"
color:1,1,0,1
outline:0,0,0,1
outline_width:4
font_size:32
bolde:True
size_hint_y:.8
text:"Login"
on_press:
root.getUserInfo()
root.manager.transition.direction = 'up'
root.manager.transition.duration = .9
root.manager.current = 'Login'
Label:
text:""
BoxLayout:
Label:
text:""
<LogIn>:
BoxLayout:
orientation:'vertical'
canvas.before:
Color:
rgba:0,0,1,1
Rectangle:
size:self.size
pos:self.pos
BoxLayout:
Label:
text:""
BoxLayout:
orientation:'horizontal'
BoxLayout:
size_hint_x:.4
Label:
text:""
BoxLayout:
orientation:"vertical"
TextInput:
id:username
size_hint_y:.3
hint_text:"User Name"
TextInput:
id:password
size_hint_y:.3
hint_text:"Password"
BoxLayout:
orientation:"horizontal"
Label:
size_hint_x:.3
text:""
Button:
id:LoginFromButton
on_press:
root.manager.transition.direction='left'
root.manager.transition.duration = .9
root.manager.current = 'Home'
text:'Login'
font_name:"fonts/MTCORSVA.TTF"
color:1,1,0,1
outline:0,0,0,1
outline_width:4
font_size:32
bolde:True
size_hint_y:.5
Label:
size_hint_x:.3
text:""
BoxLayout:
size_hint_x:.4
Label:
text:""
BoxLayout:
Label:
text:""
<Home>:
Button:
text:"Home"
In your kv, set the on_press to a method, like this:
Button:
id:LoginFromButton
on_press:
root.do_login()
Then, in the LogIn screen class:
def check_login(self):
# do your check for legal login and return True or False
return True
def do_login(self):
if self.check_login():
self.manager.current = 'Home'

AssertionError in Python / Kivy

I came across an AssertionError for a kivy script. The codes as follows:
import time
from copy import deepcopy as dc
# import modules related to kivy UI
from kivy.app import App
# kivy.require("1.9.1")
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.image import Image
# define global variables just for testing
temperature = str(25)+"°C"
humidity = str(95)+'%'
last_water = "15/04/2018 15:40"
time_next = str(4)+' hr'
kv = """
<LeftScreen>:
GridLayout:
cols: 2
Image:
id: im
source: 'C:/Users/Acer/Documents/Python Scripts/sakura.jpg'
size_hint: 0.5, 0.5
Label:
id: title
text: '[b][i]Smart[/i]'+' Gardener[/b]'
color: (0.25,0.5,0.1,1)
font_size: 60
font_name: 'times'
Label:
id: group
text: '[i]group 8[/i]'
color: (0.3,0.3,0.6,1)
font_size: 45
font_name: 'Arial'
valign: 'bottom'
Label:
id: lastU
text: '[i]'+'Last Update: '+time.striftime("%H:%M:%S")+'[/i]'
font_size: 18
halign: 'center'
valign: 'middle'
Button:
id: update
text: 'Refresh'
font_size: 20
halign: 'center'
valign: 'middle'
on_press: root.reload()
Label:
id: temp_lbl
text: 'Temperature: '
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: temp_val
text: root.temp
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: hum_lbl
text: 'Humidity: '
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: hum_val
text: root.hum
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: lastW_lbl
text: 'Last Watering: '
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: lastW_val
text: root.last_water
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: nextW_lbl
text: 'Time before Next Watering: '
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: nextW_val
text: root.time_text
font_size: 24
halign: 'center'
valign: 'middle'
"""
Builder.load_string(kv)
# create the left screen
class LeftScreen(Screen):
def __init__(self, **kwargs):
super(LeftScreen, self).__init__(**kwargs)
self.temp = dc(temperature)
self.hum = dc(humidity)
self.last_water = dc(last_water)
self.time_next = dc(time_next)
def reload(self,value):
self.ids.lastU.text='Last Update: '+time.strftime("%H:%M:%S")
self.ids.temp_val.text=temperature
self.ids.hum_val.text=humidity
self.ids.lastW_val.text=last_water
self.ids.nextW_val.text=time_next
class RightScreen(Screen):
def __init__(self,**kwargs):
super(RightScreen,self).__init__(**kwargs)
self.layout = GridLayout()
self.add_widget(self.layout)
class SmartGardener(App):
def build(self):
sm = ScreenManager()
ls = LeftScreen(name='data')
sm.add_widget(ls)
sm.current = 'data'
return sm
def reset():
import kivy.core.window as window
from kivy.base import EventLoop
if not EventLoop.event_listeners:
from kivy.cache import Cache
window.Window = window.core_select_lib('window', \
window.window_impl, True)
Cache.print_usage()
for cat in Cache._categories:
Cache._objects[cat] = {}
myApp = SmartGardener()
if __name__ == '__main__':
reset()
myApp.run()
Is the error with the image that I inserted or the variables I used for the labels? I want to insert the image as the background of the UI.
Also, there seems to be some error with the variable 'time_next' when I tried to accessing it from the kivy file. What is the right way to access the attribute 'time_next' of object MainScreen in the kv quote?
Okay, i tried to run your code and here is what i found:
you try to access 'time_text' in kv file, while you set in the class 'time_next', that's a typo but even after i fixed it i had to set defaults in the kv file for all the variables that you call, hum, temp, time_next, last_water:
<LeftScreen>:
time_text: ''
last_water:''
hum: ''
temp: ''
GridLayout:
cols: 2
...
next you use the time.striftime which is a typo to time.strftime, yet you need to import it in the kv code like so:
:import strftime time.strftime
<LeftScreen>:
...
and use it like:
Label:
id: lastU
text: '[i]'+'Last Update: '+strftime("%H:%M:%S")+'[/i]'
see the kv language docs for it: under special syntax
i wasn't able to run your code yet, i didn't have the Fonts you used, so i simply commented those lines, and once it ran i noticed that the Label's show the markup, to use it you need to explicitly set markupe=True
Label:
id: title
text: '[b][i]Smart[/i]'+' Gardener[/b]'
markup: True
color: (0.25,0.5,0.1,1)
font_size: 60
#font_name: 'times'
Label:
id: group
text: '[i]group 8[/i]'
markup: True
color: (0.3,0.3,0.6,1)
font_size: 45
#font_name: 'Arial'
valign: 'bottom'
At last, clicking the refresh button calls reload without any value, while it expects some value, so the 'refresh' button would raise a TypeError.

Getting value from slider to display on a different screen (python, kivy)

I am trying to display the value of a slider on a different screen. i have tried this(below code) but for some reason, the value doesn't seem to show up. the code runs fine but no value is returned. Thanks for your help :) Cheers.
temperature screen
here is a snippet of the python code:
class Thermostat(Screen):
label = StringProperty()
def display(self):
tempVal = self.label
return str(tempVal)
and the kv files:
<Thermostat>:
name: "thermostat"
BoxLayout:
orientation: 'horizontal'
cols: 2
Label:
id: label
font_size: "11sp"
text: "INSIDE: " + root.display()
Label:
text: "More Info"
font_size: "11sp"
kv file 2:This screen holds the true value from the slider, i am trying to pass that value to the Thermostat screen.
<Temperature>:
BoxLayout:
size_hint_y: None
height: '48dp'
cols: 3
Label:
text: 'THERMOSTAT'
Slider:
id: temp
min: 40
max: 100
value: 1
step: 1
on_value: app.root.get_screen('thermostat').label = str('{}'.format(temp.value))
Label:
id: slide_val
text: '{}'.format(temp.value)
root.display is only called once, at the beginning of the program. For it to work well, every time you change the value of the slider root.display should be called.
However, it is very simple to do this using propertis in kv languaje:
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang.builder import Builder
Builder.load_string('''
<Manager>:
id: manager
Thermostat:
id: thermostat
name: 'thermostat'
manager: 'screen_manager'
temp: temperature.temp #<<<<<<<<<<<<
Temperature:
id: temperature
name: 'temperature'
manager: 'screen_manager'
<Thermostat>:
temp: 0 #<<<<<<<<<<<<
BoxLayout:
orientation: 'horizontal'
cols: 3
Label:
id: label
font_size: "11sp"
text: "INSIDE: {}".format(root.temp) #<<<<<<<<<<<<
Label:
text: "More Info"
font_size: "11sp"
Button:
text: ">"
on_release: app.root.current= "temperature"
size_hint_x: None
width: 30
<Temperature>:
temp: temp_slider.value #<<<<<<<<<<<<
BoxLayout:
cols: 4
Button:
text: "<"
on_press: app.root.current = "thermostat"
size_hint_x: None
width: 30
Label:
text: 'THERMOSTAT'
Slider:
id: temp_slider
min: 40
max: 100
value: 40
step: 1
Label:
id: slide_val
text: str(root.temp)
''')
class Thermostat(Screen):
pass
class Temperature(Screen):
pass
class Manager(ScreenManager):
pass
class ExampleApp(App):
def build(self):
return Manager()
if __name__ == "__main__":
ExampleApp().run()
If you want to use the slider's value in your class Temperature, simply declare the property in the class:
from kivy.properties import NumericProperty
class Temperature(Screen):
temp = NumericProperty()
def __init__(self, **kwargs):
super(Temperature, self).__init__(**kwargs)

Categories

Resources