Access python list in kivy file - python

I'm a physicist, and as everyone knows, we like our cocktails. I am therefore trying to build an automatic bartender. Unfortunately, the only experience I have with programming in python is to do physics simulations, and I am not that savvy with coding anyways.
My problem is now this: there is a python list in the class BartenderApp that I want to use in the kivy file, specifically in the LoadNewIngredients in the kivy file, for the spinners to take their options from. I have looked quite a while for a solution and none have worked so far. I know I should be able to put the spinners and labels in the python file using a for loop, but I would much rather have it a bit more clean and keep them in the kivy file.
So if anyone could help me how to pass the list to the kivy file, it'd be much appreciated!
Here is the .py file:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.clock import mainthread
from functools import partial
#Import drink list
from drinks import drink_list, drink_options
class drink:
def __init__(self,name,ingredients,amount):
self.name = name
self.ingredients = ingredients
self.amount = amount
#Define the different screens
class MainMenu(Screen):
pass
class UseLastIngredients(Screen):
pass
class DrinkMenu(Screen):
#Mainthread will pause shortly to give script time, the rest adds the buttons
#mainthread
def on_enter(self):
self.buttons = []
self.ids.drinks.clear_widgets()
for btn in range(len(drink_list)):
self.buttons.append(Button(text=str(drink_list[btn]['name'])))
self.buttons[btn].bind(on_press = self.pour_drink)
self.ids.drinks.add_widget(self.buttons[btn])
def pour_drink(self, button):
print(button.text)
class LoadNewIngredients(Screen):
def spinner_clicked(self, ident, value):
if ident == 1:
pass
if ident == 2:
pass
if ident == 3:
pass
if ident == 4:
pass
if ident == 5:
pass
if ident == 6:
pass
if ident == 7:
pass
if ident == 8:
pass
#Define the ScreenManager
class MenuManager(ScreenManager):
pass
#Designate the .kv design file
kv = Builder.load_file('bartenderkv.kv')
class BartenderApp(App):
#I want to use the ingredients list in the kivy file
global ingredients
ingredients = []
for drink in range(len(drink_list)):
ings = list(drink_list[drink]['ingredients'].keys())
for ing in range(len(ings)):
elem = ings[ing]
if elem not in ingredients:
ingredients.append(elem)
def build(self):
return kv
if __name__ == '__main__':
BartenderApp().run()
and here is the .kv file:
#:import Factory kivy.factory.Factory
#:import ScrollView kivy.uix.scrollview
MenuManager:
MainMenu:
LoadNewIngredients:
DrinkMenu:
<MainMenu>:
name: "MainMenu"
GridLayout:
rows: 3
size: root.width, root.height
padding: 10
spacing: 10
Label:
text: "Main Menu"
font_size: 32
GridLayout:
cols: 2
size: root.width, root.height
spacing: 10
Button:
text: "Use Last Ingredients"
font_size: 32
on_release: app.root.current = "DrinkMenu"
Button:
text: "Load New Ingredients"
font_size: 32
on_release: app.root.current = "LoadNewIngredients"
Button:
text: "See Permissable Ingredients"
font_size: 32
#on_press: print("It Works")
on_release: Factory.PermissablePopup().open()
<LoadNewIngredients>:
name: "LoadNewIngredients"
GridLayout:
cols: 2
size: root.width, root.height
padding: 10
spacing: 10
GridLayout:
size: root.width, root.height
size_hint_x: 0.4
rows: 2
Button:
text: "Continue"
font_size: 24
on_release: app.root.current = "DrinkMenu"
Button:
text: "Main Menu"
font_size: 24
on_release: app.root.current = "MainMenu"
GridLayout:
#This is where I want the spinners to take in the ingredients list as options.
id: choices
rows: 4
orientation: 'tb-lr'
Label:
id: pump_1
text: "Pump 1"
font_size: 24
Label:
id: pump_2
text: "Pump 2"
font_size: 24
Label:
id: pump_3
text: "Pump 3"
font_size: 24
Label:
id: pump_4
text: "Pump 4"
font_size: 24
#Spinner is the easy drop down version in kivy, lets see how it looks.
Spinner:
id: spinner_id_1
text: "Pump_1"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(1,spinner_id_1.text)
Spinner:
id: spinner_id_2
text: "Pump_2"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(2,spinner_id_2.text)
Spinner:
id: spinner_id_3
text: "Pump_3"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(3,spinner_id_3.text)
Spinner:
id: spinner_id_4
text: "Pump_4"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(4,spinner_id_4.text)
Label:
id: pump_5
text: "Pump 5"
font_size: 24
Label:
id: pump_6
text: "Pump 6"
font_size: 24
Label:
id: pump_7
text: "Pump 7"
font_size: 24
Label:
id: pump_8
text: "Pump 8"
font_size: 24
#Spinner is the drop down version, lets see how it looks.
Spinner:
id: spinner_id_5
text: "Pump_5"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(5,spinner_id_5.text)
Spinner:
id: spinner_id_6
text: "Pump_6"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(6,spinner_id_6.text)
Spinner:
id: spinner_id_7
text: "Pump_7"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(7,spinner_id_7.text)
Spinner:
id: spinner_id_8
text: "Pump_8"
values: ["1", "2", "3"]
on_text: root.spinner_clicked(8,spinner_id_8.text)
<DrinkMenu>:
name: "DrinkMenu"
GridLayout:
cols: 2
width: root.width
height: self.minimum_height
padding: 10
spacing: 10
GridLayout:
height: root.height
size_hint_x: 0.4
rows: 2
Button:
text: "Top Up"
font_size: 24
on_release:
Button:
text: "Main Menu"
font_size: 24
on_release: app.root.current = "MainMenu"
ScrollView:
size_hint_y: 0.73
pos_hint: {'x':0, 'y': 0.11}
do_scroll_x: False
do_scroll_y: True
GridLayout:
id: drinks
orientation: 'lr-tb'
size_hint_y: None
size_hint_x: 1.0
cols: 3
height: self.minimum_height
row_default_height: 180
row_force_default: True
#Create a rounded button, the #Button is what it inherits
<RoundedButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba:
(48/255,84/255,150/255,1)\
if self.state == 'normal' else (0.6,0.6,1,1) # Color is red if button is not pressed, otherwise color is green
RoundedRectangle:
size: self.size
pos: self.pos
radius: [58]
<PermissablePopup#Popup>
auto_dismiss: False
#size_hint: 0.6,0.2
#pos_hint: {"x":0.2, "top":0.9}
title: "Permissable Ingredients"
GridLayout:
rows: 2
size: root.width, root.height
spacing: 10
GridLayout:
cols: 2
Label:
text: "Sodas"
font_size: 32
#Add list of sodas
Label:
text: "Alcohol"
font_size: 32
#Add list of alcohols
Button:
text: "Done"
font_size: 24
on_release: root.dismiss()

Try adding a ListProperty (https://kivy.org/doc/stable/api-kivy.properties.html) to you App class. Like this:
class BartenderApp(App):
ingredients = ListProperty()
for drink in range(len(drink_list)):
ings = list(drink_list[drink]['ingredients'].keys())
for ing in range(len(ings)):
elem = ings[ing]
if elem not in self.ingredients:
self.ingredients.append(elem)
A list property is both accessible in the Python and KV file. What's more is that they can be bound to a callback so that you can create your own event!
In the KV file you can now refer to app.ingredients and any object that is defined by the list will be automatically updated when app.ingredients is changed. So for example if you had the following label in your KV file:
Label:
text: app.ingredients[0]
The text would automatically update when you change the list. Be careful though, you may get an index error if there isn't an object in the index you're referencing.
Let me know how you get on with this and whether it solves your problem.

I finally managed to solve it, maybe not the best solution, but it works.
In the class LoadNewIngredients I wrote a function that checked what ingredients are available and returns a list with the ingredients. This function is then referenced in the kivy app using root.function_name().
The .py file:
#Everything needed for kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.clock import mainthread
from functools import partial
#Import drink list
from drinks import drink_list, drink_options
class drink:
def __init__(self,name,ingredients,amount):
self.name = name
self.ingredients = ingredients
self.amount = amount
#Define the different screens
class MainMenu(Screen):
pass
class UseLastIngredients(Screen):
pass
class DrinkMenu(Screen):
#Mainthread will pause shortly to give script time, the rest adds the buttons
#mainthread
def on_enter(self):
self.buttons = []
self.ids.drinks.clear_widgets()
for btn in range(len(drink_list)):
self.buttons.append(Button(text=str(drink_list[btn]['name'])))
self.buttons[btn].bind(on_press = self.pour_drink)
self.ids.drinks.add_widget(self.buttons[btn])
def pour_drink(self, button):
print(button.text)
class LoadNewIngredients(Screen):
def spinner_clicked(self, ident, value):
if ident == 1:
pass
if ident == 2:
pass
if ident == 3:
pass
if ident == 4:
pass
if ident == 5:
pass
if ident == 6:
pass
if ident == 7:
pass
if ident == 8:
pass
#I want to use the ingredients list in the kivy file
def get_ingredients(self,*args,**kwargs):
global ingredients
ingredients = []
for drink in range(len(drink_list)):
ings = list(drink_list[drink]['ingredients'].keys())
for ing in range(len(ings)):
elem = ings[ing]
if elem not in ingredients:
ingredients.append(elem)
return ingredients
#Define the ScreenManager
class MenuManager(ScreenManager):
pass
#Designate the .kv design file
kv = Builder.load_file('bartenderkv.kv')
class BartenderApp(App):
def build(self):
return kv
if __name__ == '__main__':
BartenderApp().run()
and here is the .kv file:
#Need to define everything, the ScreenManager is the entity that keeps tabs
#on all the different menu windows
#This is for the popup, lets you instansiate a class from anywhere
#:import Factory kivy.factory.Factory
#:import ScrollView kivy.uix.scrollview
MenuManager:
MainMenu:
LoadNewIngredients:
DrinkMenu:
<MainMenu>:
name: "MainMenu"
GridLayout:
rows: 3
size: root.width, root.height
padding: 10
spacing: 10
Label:
text: "Main Menu"
font_size: 32
GridLayout:
cols: 2
size: root.width, root.height
spacing: 10
Button:
text: "Use Last Ingredients"
font_size: 32
on_release: app.root.current = "DrinkMenu"
Button:
text: "Load New Ingredients"
font_size: 32
on_release: app.root.current = "LoadNewIngredients"
Button:
text: "See Permissable Ingredients"
font_size: 32
on_release: Factory.PermissablePopup().open()
<LoadNewIngredients>:
name: "LoadNewIngredients"
GridLayout:
cols: 2
size: root.width, root.height
padding: 10
spacing: 10
#size hint sets relative sized, x-dir, y-dir
GridLayout:
size: root.width, root.height
size_hint_x: 0.4
rows: 2
Button:
text: "Continue"
font_size: 24
on_release: app.root.current = "DrinkMenu"
Button:
text: "Main Menu"
font_size: 24
on_release: app.root.current = "MainMenu"
GridLayout:
id: choices
rows: 4
orientation: 'tb-lr'
Label:
id: pump_1
text: "Pump 1"
font_size: 24
Label:
id: pump_2
text: "Pump 2"
font_size: 24
Label:
id: pump_3
text: "Pump 3"
font_size: 24
Label:
id: pump_4
text: "Pump 4"
font_size: 24
Spinner:
id: spinner_id_1
text: "Pump_1"
#This references the get_ingredients function in the main py file
values: root.get_ingredients()
on_text: root.spinner_clicked(1,spinner_id_1.text)
Spinner:
id: spinner_id_2
text: "Pump_2"
values: root.get_ingredients()
on_text: root.spinner_clicked(2,spinner_id_2.text)
Spinner:
id: spinner_id_3
text: "Pump_3"
values: root.get_ingredients()
on_text: root.spinner_clicked(3,spinner_id_3.text)
Spinner:
id: spinner_id_4
text: "Pump_4"
values: root.get_ingredients()
on_text: root.spinner_clicked(4,spinner_id_4.text)
Label:
id: pump_5
text: "Pump 5"
font_size: 24
Label:
id: pump_6
text: "Pump 6"
font_size: 24
Label:
id: pump_7
text: "Pump 7"
font_size: 24
Label:
id: pump_8
text: "Pump 8"
font_size: 24
Spinner:
id: spinner_id_5
text: "Pump_5"
values: root.get_ingredients()
on_text: root.spinner_clicked(5,spinner_id_5.text)
Spinner:
id: spinner_id_6
text: "Pump_6"
values: root.get_ingredients()
on_text: root.spinner_clicked(6,spinner_id_6.text)
Spinner:
id: spinner_id_7
text: "Pump_7"
values: root.get_ingredients()
on_text: root.spinner_clicked(7,spinner_id_7.text)
Spinner:
id: spinner_id_8
text: "Pump_8"
values: root.get_ingredients()
on_text: root.spinner_clicked(8,spinner_id_8.text)
<DrinkMenu>:
name: "DrinkMenu"
GridLayout:
cols: 2
width: root.width
height: self.minimum_height
padding: 10
spacing: 10
GridLayout:
height: root.height
size_hint_x: 0.4
rows: 2
Button:
text: "Top Up"
font_size: 24
on_release:
Button:
text: "Main Menu"
font_size: 24
on_release: app.root.current = "MainMenu"
ScrollView:
size_hint_y: 0.1
pos_hint: {'x':0, 'y': 0.11}
do_scroll_x: False
do_scroll_y: True
GridLayout:
id: drinks
orientation: 'lr-tb'
size_hint_y: None
size_hint_x: 1.0
cols: 3
height: self.minimum_height
row_default_height: 100
row_force_default: True
<RoundedButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba:
(48/255,84/255,150/255,1)\
if self.state == 'normal' else (0.6,0.6,1,1)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [58]
<PermissablePopup#Popup>
auto_dismiss: False
#size_hint: 0.6,0.2
#pos_hint: {"x":0.2, "top":0.9}
title: "Permissable Ingredients"
GridLayout:
rows: 2
size: root.width, root.height
spacing: 10
GridLayout:
cols: 2
Label:
text: "Sodas"
font_size: 32
#Add list of sodas
Label:
text: "Alcohol"
font_size: 32
#Add list of alcohols
Button:
text: "Done"
font_size: 24
on_release: root.dismiss()
Hopefully this helps if someone else has the same problem.
But if anyone has any other solutions (or suggestions about the code in general), please let me know!

Related

Delete a row in Kivy's BoxLayout

With Kivy, I want a layout that is different when the window size is portrait or landscape (a grid of buttons, and for exemple the buttons on a row are shown in a column).
I tried first to hide some widgets, but that doesn't work well (even at a size of 0, some text appears, and this doesn't work with spacing)
So I wanted to delete a row directly, it worked, but...
The space for the raw remains with, like this
I tried to delete the second row, but there is now a gap.
Here is the code for that example
test3.kv file
<MDBoxLayout>:
spacing:5
<MyLayout>:
MDBoxLayout:
orientation: "vertical"
size: root.width, root.height
id: vbox
# Texte
MDLabel:
size_hint: 1,0.4
text: "Text"
halign: 'left'
valign: 'bottom'
font_size: 48
id: label
# Ligne 1
MDBoxLayout:
orientation: "horizontal"
size_hint: 1,0.15
id: ligne1
MDFillRoundFlatButton:
size_hint: 0.25,1
text: "A"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"B"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"C"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"D"
# Ligne 2
MDBoxLayout:
orientation: "horizontal"
size_hint: 1,0.15
id: ligne2
MDFillRoundFlatButton:
size_hint: 0.25,1
text: "1"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"2"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"3"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"4"
# Ligne 3
MDBoxLayout:
orientation: "horizontal"
size_hint: 1,0.15
MDFillRoundFlatButton:
size_hint: 0.25,1
text: "E"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"F"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"G"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"H"
# Ligne 4
MDBoxLayout:
orientation: "horizontal"
size_hint: 1,0.15
MDFillRoundFlatButton:
size_hint: 0.25,1
text: "I"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"J"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"K"
MDFillRoundFlatButton:
size_hint: 0.25,1
text:"L"
test3.py file
import kivy
kivy.require('1.1.1')
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivymd.uix.boxlayout import MDBoxLayout
Builder.load_file('test3.kv')
class MyLayout(Widget):
def on_size(self, *args):
self.ids.label.text = 'on_size'
if self.width > self.height:
self.ids.label.text = self.ids.label.text + f' horizontal {self.ids.ligne2}'
# orientation : horizontal
if isinstance(self.ids.ligne2, MDBoxLayout):
self.ids.label.text = self.ids.label.text + ' ligne 2 existe: supprimée'
self.ids.ligne2.clear_widgets()
self.remove_widget(self.ids.ligne2)
self.ids.ligne2 = None
class app(MDApp):
def build(self):
return MyLayout()
if __name__ == '__main__':
app().run()
Is this something missing in my code, or should I try another method to change dynamically the layout?

How to output the value to the screen from textinput in kivi?

I'm a new coder and I have so many things I don't understand. I'm making a book management GUI, buy and sell books.
main.py
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.widget import Widget
#Define our different screens
class FirstWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('images.kv')
class MyLayout(Widget):
pass
class QuanlyApp(App):
def build(self):
return kv
if __name__=='__main__':
QuanlyApp().run()
images.kv
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
BoxLayout:
Button:
text: "enter"
font_size: 32
size: 100, 50
pos: root.x, root.top - 50
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
Button:
text: "import"
font_size: 32
size: 100, 50
pos: root.x - 50, root.top
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "hi"
font_size: 24
GridLayout:
cols: 2
rows: 7
Label:
text: "Ten sach"
id: name
color: '6EE369'
TextInput:
id: name
multiline: False
Label:
text: "Tac gia"
color: '6EE369'
TextInput:
id: author
multiline: False
Label:
text: "The loai"
color: '6EE369'
TextInput:
id: kind
multiline: False
Label:
text: "Ma"
color: '6EE369'
TextInput:
id: id
multiline: False
Label:
text: "Gia nhap"
color: '6EE369'
TextInput:
id: price1
multiline: False
Label:
text: "Gia xuat"
color: '6EE369'
TextInput:
id: price2
multiline: False
Button:
text: "buy"
font_size: 24
size: 100, 50
background_color: 'E36982'
background_normal: ''
Button:
text: "sell"
font_size: 24
size: 100, 50
background_color: '82E369'
background_normal: ''
The result I want is:
enter image description here
and
enter image description here
I can print value from images.kv but I can't find how to print the values of two TextInputs when a button is pressed.
This is the first time I have posted so I have a lot of mistakes. Thanks if I can get any help from everyone.

Updating Data from Kivy Python to Excel

I have a problem on updating data that I want to insert to excel. At first, I create the data and it work successfully without error. After I want to insert new data from Kivy, it doesn't work. Error said that the process denied by PC. I had watch tutorial and it seem my problem still unsolved. Here is my code from VSCode:
Window.size = (500, 500)
outWorkbook = xlsxwriter.Workbook("staff.xlsx")
outSheet = outWorkbook.add_worksheet()
class Menu(Screen):
pass
class Enter(Screen):
input1 = ObjectProperty(None)
input2 = ObjectProperty(None)
input3 = ObjectProperty(None)
input4 = ObjectProperty(None)
input5 = ObjectProperty(None)
input6 = ObjectProperty(None)
def clear(self):
self.ids.inherent_input.text = ''
self.ids.inherent2_input.text = ''
self.ids.inherent3_input.text = ''
self.ids.inherent4_input.text = ''
self.ids.inherent5_input.text = ''
self.ids.inherent6_input.text = ''
def btn(self):
self.L = ()
print("Name: " + self.input1.text,
"Activity/Programme: " + self.input2.text,
"Date: " + self.input3.text,
"Place: " + self.input4.text,
"Time from: " + self.input5.text,
"Time to: " + self.input6.text)
staff = ({"Name": [str(self.input1.text)], "Program/Activity": [str(self.input2.text)], "Place" : [str(self.input3.text)], "Date": [str(self.input4.text)], "Time From" : [str(self.input5.text)], "Time To" : [str(self.input6.text)]})
self.L = pd.DataFrame(staff)
self.input1.text = ''
self.input2.text = ''
self.input3.text = ''
self.input4.text = ''
self.input5.text = ''
self.input6.text = ''
print(self.L)
with pd.ExcelWriter('staff.xlsx') as writer:
self.L.to_excel(writer)
class Info(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('window.kv')
class MyLayout(Widget):
class WindowApp(App):
def build(self):
return kv
if name == 'main':
WindowApp().run()
And here is my kv file:
WindowManager:
Menu:
Enter:
Info:
:
name: "MainMenu"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 10
spacing: 15
Button:
id: enter
text: "Enter"
on_release: app.root.current = "enter"
Button:
id: info
text: "Information"
on_release: app.root.current = "info"
Button:
id: exit
text: "Exit"
on_press: quit()
:
name: "enter"
input1: inherent_input
input2: inherent2_input
input3: inherent3_input
input4: inherent4_input
input5: inherent5_input
input6: inherent6_input
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding:10
spacing:10
BoxLayout:
spacing: 10
Label:
text: "Name"
font_size: 20
TextInput:
id: inherent_input
multiline: False
BoxLayout:
spacing: 10
Label:
text: "Activity/Programme"
font_size: 20
TextInput:
id: inherent2_input
multiline: False
BoxLayout:
spacing: 10
Label:
text: "Place"
font_size: 20
TextInput:
id: inherent3_input
multiline: False
BoxLayout:
Label:
text: "Date"
font_size: 20
TextInput:
id: inherent4_input
multiline: False
BoxLayout:
padding: 10
spacing: 10
Label:
text: "Time from"
font_size: 20
TextInput:
id: inherent5_input
multiline: False
Label:
text: "to"
font_size: 20
TextInput:
id: inherent6_input
multiline: False
BoxLayout:
padding: 15
spacing: 15
Button:
id: clear
text: "Clear"
font_size: 12
on_press: root.clear()
Button:
id: back
text: "Back to Menu"
font_size: 12
on_release: app.root.current = "MainMenu"
Button:
id: submit
text: "Submit"
font_size: 12
on_press: root.btn()
:
name: "info"
BoxLayout:
orientation: 'vertical'
padding: 15
spacing: 15
Label:
id: information
text: "This is just a test, an Alpha version of Prototype"
font_size: 20
bold: True
italic: False
outline_color: (0,0,0)
Button:
id: returnBack
text: "Return"
on_release: app.root.current = "MainMenu"
Any help will be appreciated.
The error you're getting can mean multiple things.
Are you trying to open a directory?
If so, don't do it. It will most likely result in the error you mentioned.
Is the file you are trying to opened anywhere else?
You may have to close it, for python to open it. You probably have experienced this before when trying to delete a file in the explorer, that is opened somewhere else. Windows won't let you do this. Check whether the file in question is opened before trying to access it.

KIVY: adding buttons in a sub layout when a button is pressed (on_release)

The screen has multiple layouts all child of a box layout. I am trying to add a button in the last sub layout (grid-layout) when a button in other layout is clicked. The code does not crash but nothing happens too. I want to add buttons to the layout with id drinkslayout when a button is clicked eg pepsi,sprite
Python:
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class Stacks(StackLayout):
pass
present=Builder.load_file('hellokivy2.kv') #Specifying location of kv file
class MainApp(App):
def build(self):
return present
def drinksSelect(self,value): #creating a button by referring the id of the layout in which to create button
print(value)
yolo = AnotherScreen()
yolo2 = yolo.ids.newButtonLayout
button = Button(text="value",size_hint= (0.2,0.4))
yolo2.add_widget(button)
if __name__ == "__main__":
MainApp().run()
KV
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size:root.size
Button:
text: "Slideshow"
GridLayout:
cols: 2
Button:
text: "Burger"
Button:
text: "Drinks"
on_release: app.root.current = "other"
Button:
text: "Fries"
Button:
text: "Others"
Label:
text: "Your Cart"
font_size: 40
color:(0,0,0,1)
size_hint_y: None
canvas.before:
Color:
rgba:150,10,200,0.5
Rectangle:
pos: self.pos
size: self.size
<AnotherScreen>:
name: "other"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size:root.size
orientation: 'vertical'
GridLayout:
size_hint_y:0.1
orientation: 'vertical'
rows: 1
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Back Home"
on_release: app.root.current = "main"
Label:
text: "Project BAM"
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Profile"
on_release: app.root.current = "main"
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.9
text: "Whats New"
on_release: app.root.current = "main"
GridLayout:
rows: 2
Button:
text: "Pepsi"
on_release: app.drinksSelect(1)
Button:
text: "7up"
on_release: app.drinksSelect(2)
Button:
text: "Fanta"
on_release: app.drinksSelect(3)
Button:
text: "Mountain Dew"
on_release: app.drinksSelect(4)
Button:
text: "Diet Pepsi"
on_release: app.drinksSelect(5)
Button:
text: "Sprite"
on_release: app.drinksSelect(6)
GridLayout:
id: drinksLayout
size_hint_y: 0.3
orientation: 'horizontal'
rows: 1
Button:
id: label1
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label2
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label3
size_hint: 0.2,0.4
background_normal:'1.jpg'
text: 'B1'
Ok the problem was your drinksSelect method, also you need to keep the value of your screens
Try this:
py:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
dl = ObjectProperty()
l = 0
limit = 3 # Fix your limit here 3 is an example
class ScreenManagement(ScreenManager):
m_s = ObjectProperty() # Here I will keep the value of the MainScreen
a_s = ObjectProperty() # Here the AnotherScreen so I can use them later
class Stacks(StackLayout):
pass
present = Builder.load_file('hellokivy2.kv') # Specifying location of kv file
class MainApp(App):
def build(self):
return present
def drinksSelect(self,value): # creating a button by referring the id of the layout in which to create button
print(value)
if self.root.a_s.l < self.root.a_s.limit: # You know what I mean
button = Button(text=str(value), size_hint= (0.2,0.4))
self.root.a_s.ids['place_remaining'].add_widget(button)
self.root.a_s.l += 1
if __name__ == "__main__":
MainApp().run()
kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
m_s: m_s # so I can use it in the .py file
a_s:a_s # same here
transition: FadeTransition()
MainScreen:
id: m_s
AnotherScreen:
id: a_s
<MainScreen>:
name: "main"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size:root.size
Button:
text: "Slideshow"
GridLayout:
cols: 2
Button:
text: "Burger"
Button:
text: "Drinks"
on_release: app.root.current = "other"
Button:
text: "Fries"
Button:
text: "Others"
Label:
text: "Your Cart"
font_size: 40
color:(0,0,0,1)
size_hint_y: None
canvas.before:
Color:
rgba:150,10,200,0.5
Rectangle:
pos: self.pos
size: self.size
<AnotherScreen>:
name: "other"
dl : drinksLayout
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size:root.size
orientation: 'vertical'
GridLayout:
size_hint_y:0.1
orientation: 'vertical'
rows: 1
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Back Home"
on_release: app.root.current = "main"
Label:
text: "Project BAM"
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.1
text: "Profile"
on_release: app.root.current = "main"
Button:
color: 1,1,1,1
font_size: 25
size_hint_y:0.9
text: "Whats New"
on_release: app.root.current = "main"
GridLayout:
rows: 2
Button:
text: "Pepsi"
on_release: app.drinksSelect(1)
Button:
text: "7up"
on_release: app.drinksSelect(2)
Button:
text: "Fanta"
on_release: app.drinksSelect(3)
Button:
text: "Mountain Dew"
on_release: app.drinksSelect(4)
Button:
text: "Diet Pepsi"
on_release: app.drinksSelect(5)
Button:
text: "Sprite"
on_release: app.drinksSelect(6)
GridLayout:
id: drinksLayout
size_hint_y: 0.3
orientation: 'horizontal'
rows: 1
GridLayout:
id: place_remaining
rows: 1
size_hint_x: 80
Button:
id: label1
width: 40 # Set the size_hint_x to None and then set the width if you want a fixed dimension
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label2
width: 40
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Button:
id: label3
width: 40
size_hint: None,0.4
background_normal:'1.jpg'
text: 'B1'
Outputs:
I hope that the code is a bit clear now

Kivy input values for simple calculations

I'm quite new to Kivy (started yesterday) and am trying to create a simple enough app that has input boxes for several values of height and area to calculate volumes. I cant find any working methods of doing this. So far all I have got is this:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_string("""
<MenuScreen>:
FloatLayout:
Label:
text: 'Please Select an Area to Work With:'
pos: 230, 490
size_hint: .15, .05
font_size: 23
Button:
text: "A"
pos: 230, 100
size_hint: .4,.1
font_size: 23
on_press: root.manager.current = 'settings'
Button:
text: "B"
pos: 230, 210
size_hint: .4,.1
font_size: 23
on_press: root.manager.current = 'settings'
Button:
text: "C"
pos: 230, 320
size_hint: .4,.1
font_size: 23
on_press: root.manager.current = 'settings'
Button:
text: "D"
pos: 230, 420
size_hint: .4,.1
font_size: 23
on_press: root.manager.current = 'settings'
<SettingsScreen>:
GridLayout:
Label:
text: 'Room 1'
pos: 6, 460
size_hint: .15, .05
font_size: 23
Label:
text: 'Room 2'
pos: 6, 420
size_hint: .15, .05
font_size: 23
Label:
text: 'Room 3'
pos: 6, 380
size_hint: .15, .05
font_size: 23
Label:
text: 'Room 4'
pos: 6, 340
size_hint: .15, .05
font_size: 23
Label:
text: 'Room 5'
pos: 6, 300
size_hint: .15, .05
font_size: 23
Label:
text: 'Room 6'
pos: 6, 260
size_hint: .15, .05
font_size: 23
TextInput:
text1: "0"
multiline: False
pos: 200,420
font_size: 23
on_text: viewer.text = self.text1
size_hint: .001, .001
TextInput:
text2: "0"
multiline: False
pos: 200, 420
font_size: 23
on_text: viewer.text = self.text2
size_hint: .001, .001
TextInput:
text3: "0"
multiline: False
pos: 200,380
font_size: 23
on_text: viewer.text = self.text3
size_hint: .001, .001
TextInput:
text4: "0"
multiline: False
pos: 200,340
font_size: 23
on_text: viewer.text = self.text4
size_hint: .001, .001
TextInput:
text5: "0"
multiline: False
pos: 200,300
font_size: 23
on_text: viewer.text = self.text5
size_hint: .001, .001
TextInput:
text6: "0"
multiline: False
pos: 200,240
font_size: 23
on_text: viewer.text = self.text6
size_hint: .001, .001
""")
# Declare both 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()
Im planning to have the second page unique for each button pressed, but want Any help would be appreciated.
I hope I got to understand your question. You are asking for methods to do this. The plain answer is that you have the whole Python to do all the operations you want. Kivy is a library that provides a lot of components to design GUI. It also provides you with a language that is parsed by the Builder.load_string(). Here is an example that might be more or less what you are looking for. It is sort of a calculator on the first screen. The second screen is empty and you can move between them with the bottom buttons.
The calculator on the first screen has two InputTexts and two buttons (Sum and Product). The Sum Button has the implementation of a sum directly on the kivy language. The Product Button calls a method in the root (an instance of Calc). The method doesn't exist by itself. I created in the python code below the kivy section. There is some comments on the code for what I am saying.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
Builder.load_string("""
<Calc>:
# This are attributes of the class Calc now
a: _a
b: _b
result: _result
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
ScreenManager:
size_hint: 1, .9
id: _screen_manager
Screen:
name: 'screen1'
GridLayout:
cols:1
TextInput:
id: _a
text: '3'
TextInput:
id: _b
text: '5'
Label:
id: _result
Button:
text: 'sum'
# You can do the opertion directly
on_press: _result.text = str(int(_a.text) + int(_b.text))
Button:
text: 'product'
# Or you can call a method from the root class (instance of calc)
on_press: root.product(*args)
Screen:
name: 'screen2'
Label:
text: 'The second screen'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .1
Button:
text: 'Go to Screen 1'
on_press: _screen_manager.current = 'screen1'
Button:
text: 'Go to Screen 2'
on_press: _screen_manager.current = 'screen2'""")
class Calc(FloatLayout):
# define the multiplication of a function
def product(self, instance):
# self.result, self.a and self.b where defined explicitely in the kv
self.result.text = str(int(self.a.text) * int(self.b.text))
class TestApp(App):
def build(self):
return Calc()
if __name__ == '__main__':
TestApp().run()

Categories