How can I avoid repetition in python/kivy? - python

I have been trying to make an app that have many functions associate to one buttons each. This way, if I have 70 buttons I have 70 different functions. I want to add, the respective value, when I click respective button, to a respective variable label (I am using numericproperty). As the change between this functions is only in this numeric value, I would like to make this in a more inteligent way than I did. Have anybody one suggestion of better way to do it without I have to repeat my code? Very thanks everybody, and part of my code is bellow.
.py
class SegundoScreen(Screen):
def __init__(self, **kwargs):
self.name = 'dois'
super(Screen,self).__init__(**kwargs)
def mucarela(self, *args):
screen4 = self.manager.get_screen('carrinho')
screen4.btn1 = BubbleButton(text="Muçarela", font_size='20dp', size_hint=(1,None), background_normal='1.png', background_down='2.png')
screen4.lb1 = Label(text="25,00", font_size='20dp', size_hint=(1,None))
screen4.ids.lb5.value += 25
screen4.ids.grid.add_widget(screen4.btn1)
screen4.ids.grid.add_widget(screen4.lb1)
def catupiry(self, *args):
screen4 = self.manager.get_screen('carrinho')
screen4.btn2 = BubbleButton(text="Catupiry",font_size='20dp', size_hint=(1,None), background_normal='2.png', background_down='1.png')
screen4.lb2 = Label(text="25,00",font_size='20dp', size_hint=(1,None))
screen4.ids.lb5.value += 25
screen4.ids.grid.add_widget(screen4.btn2)
screen4.ids.grid.add_widget(screen4.lb2)
def peru(self, *args):
screen4 = self.manager.get_screen('carrinho')
screen4.btn2 = BubbleButton(text="Peito de peru",font_size='20dp', size_hint=(1,None), background_normal='1.png', background_down='2.png')
screen4.lb2 = Label(text="95,00",font_size='20dp', size_hint=(1,None))
screen4.ids.lb5.value += 35
screen4.ids.grid.add_widget(screen4.btn2)
screen4.ids.grid.add_widget(screen4.lb2)
[...]
and .kv
StackLayout:
orientation: 'tb-lr'
ScrollView:
size_hint: (1, .9)
pos_hint:{'x': .0, 'y': .0}
GridLayout:
cols: 2
padding: 45, 50
spacing: 25, 50
size_hint: (1, 1)
size_hint_y: None
height: self.minimum_height
width: 500
Label:
text: "[b]Escolha[/b]\n[i]Sabor[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Label:
text: "[b]Preço\n[/b] [i](R$)[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Button:
text: "[b]Muçarela[/b]\n[i]Muçarela, tomate\n e orégano[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
background_normal:'1.png'
background_down:'2.png'
on_press: root.mucarela()
Label:
text: "25,00"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Button:
text: "[b]Catupiry[/b]\n[i]Catupiry, azeitona\n e tomate[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
background_normal:'2.png'
background_down:'1.png'
on_press: root.catupiry()
Label:
text: "25,00"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Button:
text: "[b]Peito de peru[/b]\n[i]Muçarela, peito de peru\n e tomate[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
background_normal:'1.png'
background_down:'2.png'
on_press: root.peru()
Label:
text: "35,00"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Button:
text: "[b]Portuguesa[/b]\n[i]Muçarela, presunto,\n cebola e ovo[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
background_normal:'2.png'
background_down:'1.png'
on_press: root.portuguesa()
Label:
text: "27,00"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
Button:
text: "[b]Toscana[/b]\n[i]Calabresa moída, muçarela\ne parmesão[/i]"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
background_normal:'1.png'
background_down:'2.png'
on_press: root.toscana()
Label:
text: "35,00"
markup: True
font_size: '20dp'
size_hint_y: None
height: self.texture_size[1]
and I have more one class form that is just one label numericpropertie whose change the value when respective button has clicked. As the change is only in this label, I am locking for how can I take the price value from the text label, and flavor name from the text button. Very thanks.

for your .kv file I recommend using Classes like
<MyButton#Button>:
markup: True
font_size: '20dp'
size_hint_y: None
then in your code you could use instances of MyButton which could minify your code a little bit.

Related

I need to put the source of TextInput inside a variable in my Main.py in kivy

I'm trying to use this id "self.ids.input_tornillo.text" and put it inside a variable in my main.py but when running this code I got this Error: "NameError: name 'self' is not define". I think the word self just work inside a function. But I don't know if it really necessary create a funcion for this or I can do it in another way. Pls someone can give me a hand? -
main.py
class FirstWindow(Screen):
#Variables Shopping Cart
var1= StringProperty("images/shoppingcart.png")
var2= StringProperty("images/shoppingcart2.png")
#Variables Items
variable= self.ids.input_tornillo.text
#Here is the problem with self, How can I put it in a variable?
main.kv
<FirstWindow>:
name: "Catalogue"
BoxLayout:
orientation:'vertical'
pos_hint: {'top': 1}
size: root.width, root.height
size_hint_y: .55
GridLayout:
size:(root.width, root.height)
size_hint_x: None
size_hint_y: None
cols:4
height: self.minimum_height
Label:
text: "Items"
#font_size: 25
Label:
text: "Number"
Label:
text: "Price"
Label:
text: "Add to Cart"
ScrollView:
size_hint_y: .80
pos_hint: {'x':0, 'y': .11}
do_scroll_x: True
do_scroll_y: True
GridLayout:
size:root.width, root.height
size_hint_x: None
size_hint_y: None
cols:4
#height: self.minimum_height
#Label:
# text: "Items"
#font_size: 25
#Label:
# text: "Number"
#Label:
# text: "Price"
#Label:
# text: "Add to Cart"
Label:
text: "Tornillos"
text_size: self.size
halign: 'center'
valign: 'bottom'
Image:
id: image_tornillos
allow_stretch: True
keep_ratio: True
size_hint: 0.2,0.2
width: 60
height: 80
#pos_hint: {'center_x':1, 'center_y':1}
source: "images/tornillo.png"
center_x: self.parent.center_x
center_y: self.parent.center_y+10
TextInput:
id: input_tornillo #I need to put this id in a variable in my main.py
text: ""
halign: "right"
font_size: 18
multiline: True
#size_hint: (1, .15)
I was thinking create a function too and make it like this
class FirstWindow(Screen):
#Variables Shopping Cart
var1= StringProperty("images/shoppingcart.png")
var2= StringProperty("images/shoppingcart2.png")
#Variables Items
def list_items(self):
tornillo= self.ids.input_tornillo.text
tornillo1= float(tornillo) * 0.10
tornillo2= str(tornillo1)
but I don't how to call my variable "tornillo2" in my main.kv either
TextInput:
id: input_tornillo
text: ""
halign: "right"
font_size: 18
multiline: True
#size_hint: (1, .15)
Label:
id: label_tornillo
#text: root.ids.input_tornillo.text*2
text: root.tornillo2
root.tornillo2 is giving me this error...
AttributeError: 'FirstWindow' object has no attribute 'tornillo2'
In the python code, define a property for the variable "tornillo2"
tornillo2 = StringProperty("")
Now you can use it in the kv file as you did it already
(text: root.tornillo2)

Create a recycle view(Gridlayout) inside a Boxlayout kivy

I need all the elements of my FirsWindow, put them in a recycleview. I'm thinking to do it from RecycleGridLayout instead of GridLayout, but I don't how to really apply it in the code. It's necesary that the GridLayout or RecycleGridLayout have cols:4, I think it's not necessary upload my py.file but I'm not sure. please I need help on this. thanks in advance.
kv.file
<FirstWindow>:
name: "Catalogue"
BoxLayout:
id: Boxmain
orientation: "vertical"
#size: root.width, root.height
#size_hint: 1, None
#height: 300
#padding: 50
spacing: 50
size: root.height, root.width
GridLayout:
cols: 4
padding: 4
Label:
text: "Items"
#font_size: 25
Label:
text: "Number"
Label:
text: "Price"
Label:
text: "Add to Cart"
Label:
text: "Tornillos"
text_size: self.size
halign: 'center'
valign: 'bottom'
Image:
id: image_tornillos
allow_stretch: True
keep_ratio: True
size_hint: 0.2,0.2
width: 60
height: 80
#pos_hint: {'center_x':1, 'center_y':1}
source: "images/tornillo.png"
center_x: self.parent.center_x
center_y: self.parent.center_y+10
TextInput:
id: input_tornillo
text: ""
halign: "right"
font_size: 18
multiline: True
#size_hint: (1, .15)
Label:
text: "0.0"
Button:
id: shopping1
#text: "Hello"
#font_size: 32
allow_stretch: True
keep_ratio: True
size_hint: .25,.30
pos_hint: {'center_x':0.5, 'center_y':0.5}
background_color: 0,0,0,0
#on_press: root.press_on()
#on_release: root.press_off()
on_press: root.ids.Shoppingcart1.source= root.var2
on_release: root.ids.Shoppingcart1.source= root.var1
Image:
id: Shoppingcart1
allow_stretch: True
keep_ratio: True
size_hint: 0.5,0.5
width: 60
height: 60
pos_hint: {'center_x':0.5, 'center_y':0.5}
source: root.var1
center_x: self.parent.center_x
center_y: self.parent.center_y
#------------------------
Button:
text:"lala"
Button:
text:"lal2"
Button:
text:"lale"
Button:
text:"lal5"
Button:
text:"lala"
Button:
text:"lal54"
Button:
text:"lala"
#------------------------------------------------------------

Change mouse pointer to 'hand' when hovering over a button of a screen in kivy Python

How can I change the mouse pointer to 'hand' when hovering over a button present in a screen along with a different widget in kivy python?
I tried creating two functions in a python file. But it changes the mouse cursor for the entire page. How can I change the cursor for just the button present on the page?
#Kivy design file
<Loginpage>:
name: "login"
Image:
source: 'background.jpg'
allow_stretch: True
keep_ratio: False
Screen:
MDCard:
size_hint: None,None
size: 400, 550
pos_hint: {"center_x":0.5,"center_y":0.5}
elevation: 10
padding: 25
spacing: 25
orientation: 'vertical'
MDLabel:
id: welcome_label
text: "Welcome"
font_size: 40
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
padding_y:15
font_style: 'H2'
MDTextField:
id: uid
hint_text: "Username"
icon_right: "account"
size_hint_x: None
width: 200
font_size: 20
pos_hint: {"center_x": 0.5}
MDTextField:
id: pwd
hint_text: "Password"
icon_right: "lock"
size_hint_x: None
width: 200
font_size: 20
pos_hint: {"center_x": 0.5}
password: True
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: root.logger()
MDRoundFlatButton:
text: "CLEAR"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: root.clear()
MDLabel:
id: login_label
text: "Invalid Login"
font_size: 14
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
pos_hint: {"center_x": 0.5}
padding_y:15
theme_text_color:'Custom'
text_color: 1,0,0,1
Widget:
size_hint_y: None
height: 10
Python File:
class Loginpage(Screen):
def enter(self, *args):
Window.set_system_cursor('hand')
class Loginpage(Screen):
def enter(self, *args):
Window.set_system_cursor('hand')
def leave(self, *args):
Window.set_system_cursor('arrow')
def logger(self):
'''code to login'''

i am trying to make the add button add another 3 textinput boxes in kivy

I am sorry if some parts are in my language hopefully it doesn't matter
When I press the 'Add' button to add another 3 textinputs like those up the 'Add' button and I want to save the input that is put on those textinput boxes but I think I can figure that myself.
I searched but couldn't find something useful. Also this is my first time creating something in this level so sorry if it is inefficient in some ways.
This is the py file:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class MyGrid(GridLayout) :
id_1 = ObjectProperty(None)
id_2 = ObjectProperty(None)
id_3 = ObjectProperty(None)
id_4 = ObjectProperty(None)
id_10 =ObjectProperty(None)
def perfundo (self) :
file = open('F:\\F\\F\\' + self.id_1.text + '-' + str(date.today()) + '.txt', 'x')
file.write('Emri dhe mbiemri :' + self.id_1.text + '\n' + 'Lloji i vetures :' + self.id_2.text + '\n' + 'Nr. i telefonit :' + self.id_3.text + '\n' + 'Problemi :' + self.id_4.text)
file.close()
def add(self):
self.id_10.text
class HAZApp(App) :
def build (self) :
return MyGrid()
app = HAZApp()
app.run()
and this is the kv file
<MyGrid>
id: HAZ
id_1: emridhembiemri
id_2:llojiivetures
id_3:numriitelefonit
id_4:problemi
id_10:add
rows: 10
padding: 10
spacing: 10
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'photo.jpg'
BoxLayout:
canvas.before:
Color:
rgba: 0.4,0.5,0.8,1
Rectangle:
size: self.size
pos: self.pos
Label:
font_size: '40sp'
outline_color: 0, 0, 0
outline_width: 2
text: 'Auto Servis "Haziri"'
BoxLayout:
spacing:10
Label:
text:"Name"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Type of car"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Phone number"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Problem"
font_size: 20
color:0.4,0.5,0.8,1
BoxLayout:
spacing:20
TextInput:
font_size: 20
id:emridhembiemri
TextInput:
font_size: 20
id:llojiivetures
TextInput:
font_size: 20
id:numriitelefonit
TextInput:
font_size: 20
id:problemi
BoxLayout:
spacing: 20
column:2
Label:
text:'Parts'
font_size: 20
color:0.4,0.5,0.8,1
BoxLayout:
Label:
text:'price for parts'
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:'price for work'
font_size: 20
color:0.4,0.5,0.8,1
BoxLayout:
spacing: 20
column:2
TextInput:
BoxLayout:
TextInput:
TextInput:
BoxLayout:
Button:
id:add
text:'Add'
on_press:root.add()
BoxLayout:
column:4
Label:
text:''
Label:
text:''
Label:
text:''
Label:
text:'Total'
BoxLayout:
column:4
Label:
text:''
Label:
text:''
Label:
text:''
Button:
text:'total'
BoxLayout:
Label:
text:''
Button:
text:'Finish'
font_size: 20
on_press:root.perfundo()
on_press: app.stop()
Label:
text:''
I recommend using a ScrollView to contain the TextInputs. Your add() method can be:
def add(self):
# Add a new PartsTextInputs inside the ScrollView
self.ids.parts_text_inputs.add_widget(Factory.PartsTextInputs())
Then add a rule for the PartsTextInputs in the kv as well as a ScrollView to contain them. Here is what a modified kv would look like:
<PartsTextInputs#BoxLayout>: # this is a rule for building the parts TextInputs
size_hint_y: None
height: self.minimum_height
spacing: 20
TextInput:
size_hint_y: None
height: 48
BoxLayout:
size_hint_y: None
height: self.minimum_height
TextInput:
size_hint_y: None
height: 48
TextInput:
size_hint_y: None
height: 48
<MyGrid>
id: HAZ
id_1: emridhembiemri
id_2:llojiivetures
id_3:numriitelefonit
id_4:problemi
id_10:add
# rows: 10
cols: 1
padding: 10
spacing: 10
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'photo.jpg'
BoxLayout:
canvas.before:
Color:
rgba: 0.4,0.5,0.8,1
Rectangle:
size: self.size
pos: self.pos
Label:
font_size: '40sp'
outline_color: 0, 0, 0
outline_width: 2
text: 'Auto Servis "Haziri"'
BoxLayout:
spacing:10
Label:
text:"Name"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Type of car"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Phone number"
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:"Problem"
font_size: 20
color:0.4,0.5,0.8,1
BoxLayout:
spacing:20
TextInput:
font_size: 20
id:emridhembiemri
TextInput:
font_size: 20
id:llojiivetures
TextInput:
font_size: 20
id:numriitelefonit
TextInput:
font_size: 20
id:problemi
BoxLayout:
spacing: 20
column:2
Label:
text:'Parts'
font_size: 20
color:0.4,0.5,0.8,1
BoxLayout:
Label:
text:'price for parts'
font_size: 20
color:0.4,0.5,0.8,1
Label:
text:'price for work'
font_size: 20
color:0.4,0.5,0.8,1
ScrollView:
size_hint_y: 3 # Since this is part of a GridLayout space is assigned by size_hint ratios
BoxLayout:
id: parts_text_inputs # this will contain all the parts TextInputs
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
PartsTextInputs: # this is the first of the parts TextInputs
BoxLayout:
Button:
id:add
text:'Add'
on_press:root.add()
BoxLayout:
column:4
Label:
text:''
Label:
text:''
Label:
text:''
Label:
text:'Total'
BoxLayout:
column:4
Label:
text:''
Label:
text:''
Label:
text:''
Button:
text:'total'
BoxLayout:
Label:
text:''
Button:
text:'Finish'
font_size: 20
on_press:root.perfundo()
on_press: app.stop()
Label:
text:''

Variables in .kv and in python code do not sync up

When I try to access TextInput that has id total_area from my python code, I get this error: AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'text'. I used debugger to see whats wrong and it seems to me that variables in python code are not getting linked to those in kv file. Help
Python code:
class RootWidget(Widget):
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'height', '720')
Config.set('graphics', 'width', '480')
koatuu_obl_cent = ObjectProperty()
koatuu_city = ObjectProperty()
kitchen_area = ObjectProperty()
qt_room = ObjectProperty()
floor = ObjectProperty()
qt_floor = ObjectProperty()
total_area = ObjectProperty()
living_area = ObjectProperty()
year_building = ObjectProperty()
#classmethod
def button_OnPress(self):
print(self.total_area.text)
class DeepEval(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
DeepEval().run()
.kv:
#:import Factory kivy.factory.Factory
<MyPopup#Popup>:
auto_dismiss: False
size_hint: None, None
size: 400, 400
<RootWidget>
koatuu_obl_cent: koatuu_obl_cent
koatuu_city: koatuu_city
kitchen_area: kitchen_area
qt_room: qt_room
floor: floor
qt_floor: qt_floor
total_area: total_area
living_area: living_area
year_building: year_building
Image:
source: 'imgs/background.jpg'
size: self.texture_size
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
size: root.width, root.height
BoxLayout:
orientation: 'vertical'
height: 350
width: 225
size_hint_x: None
size_hint_y: None
spacing: 22.5
TextInput:
id: total_area
multiline: False
hint_text: "Param12"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: kitchen_area
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: living_area
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: qt_room
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: floor
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: qt_floor
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
TextInput:
id: year_building
multiline: False
hint_text: "Param1"
halign: 'center'
foreground_color: .5, .5, .5, .75
height: 33
width: 225
size_hint_x: None
size_hint_y: None
Button:
id: koatuu_obl_cent
text: 'Open popup'
on_release: Factory.MyPopup().open()
height: 33
width: 225
size_hint_x: None
size_hint_y: None
Button:
id: koatuu_city
text: 'Open popup'
on_release: Factory.MyPopup().open()
height: 33
width: 225
size_hint_x: None
size_hint_y: None
AnchorLayout:
anchor_x: "center"
anchor_y: "bottom"
padding: 0,0,0,25
Button:
text: "Calculate"
size_hint_x: None
size_hint_y: None
height: 50
width: 135
on_press: root.button_OnPress()
AnchorLayout:
anchor_x: "right"
anchor_y: "bottom"
Button:
text: "cam"
size_hint_x: None
size_hint_y: None
height: 45
width: 45
#classmethod
def button_OnPress(self):
print(self.total_area.text)
Your wrote #classmethod so you got a class method, whose first argument is not an instance of the class (usually called self) but rather the class itself (usually called cls).
Your self.total_area is therefore equivalently RootWidget.total_area which is, as the error says, an ObjectProperty.
You need to access the total_area as an attribute of an instance of your class. In this case, remove the #classmethod.

Categories

Resources