Can anyont tell me how to call method from another class?
when i click on ok button then i call def insert(self): method.I am using code
def insert(self):
#insert data after call add_expense() method
RowsExpense().add_expense()
after insert data i call RowsExpense().add_expense().its calling because print('llllll') shows in console.But self.add_widget(r) not working because row not showing on screen.
demo.py
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.uix.popup import Popup
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Popup):
total_value = ObjectProperty(None)
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
def add_more(self):
self.ids.rows.add_more()
def add_more2(self):
self.ids.rowsExpense.add_expense()
class ExtraPopup(Popup):
mode = StringProperty("")
def __init__(self, obj, **kwargs):
super(ExtraPopup, self).__init__(**kwargs)
def add_extra(self):
self.ids.rowsExtra.add_row()
def insert(self):
#insert data after call add_expense() method
RowsExpense().add_expense()
class RowExtra(BoxLayout):
col_data = ListProperty(["?", "?", "?", "?", "?", "?", "?", "?"])
button_text = StringProperty("")
mode = StringProperty("")
def __init__(self, **kwargs):
super(RowExtra, self).__init__(**kwargs)
self.col_data[0] = ''
self.col_data[1] = ''
self.col_data[2] = ''
class RowsExtra(BoxLayout):
#orientation = "vertical"
row_count = 0
button_text = StringProperty("")
textName = StringProperty("")
def __init__(self, **kwargs):
super(RowsExtra, self).__init__(**kwargs)
def add_row(self):
for x in range(0, 3):
self.row_count += 1
r = RowExtra(button_text=str(self.row_count))
self.add_widget(r)
class Row(BoxLayout):
col_data = ListProperty(["?", "?", "?", "?", "?"])
name = ObjectProperty(None)
button_text = StringProperty("")
col_data3 = StringProperty("")
col_data4 = StringProperty("")
def __init__(self, **kwargs):
super(Row, self).__init__(**kwargs)
def add_seller_expenses(self):
self.mode = "Add"
popup = ExtraPopup(self)
popup.ids.rowsExtra.textName = self.ids.name.text
popup.ids.rowsExtra.add_row()
popup.open()
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_more()
def add_more(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class RowExpense(BoxLayout):
col_data = ListProperty(["?", "?", "?"])
button_text = StringProperty("")
def __init__(self, **kwargs):
super(RowExpense, self).__init__(**kwargs)
self.col_data[0] = ' '
class RowsExpense(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(RowsExpense, self).__init__(**kwargs)
def add_expense(self):
print('llllll')
for x in range(0, 3):
self.row_count += 1
r = RowExpense(button_text=str(self.row_count))
self.add_widget(r)
class rv(BoxLayout):
data_items = ListProperty([])
mode = StringProperty("")
def __init__(self, **kwargs):
super(rv, self).__init__(**kwargs)
def add(self):
self.mode = "Add"
popup = User()
popup.open()
class MainMenu(BoxLayout):
content_area = ObjectProperty()
def display(self):
self.rv = rv()
self.content_area.add_widget(self.rv)
class demo(App):
def build(self):
return MainMenu()
if __name__ == '__main__':
demo().run()
demo.kv
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
TextInput:
id : name
text: root.col_data3
width: 300
TextInput:
id: number_input
text: root.col_data4
width: 300
input_filter: 'int'
Button:
text: "Button"
size_hint_x: None
top: 200
on_press: root.add_seller_expenses()
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<User>:
id: user
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Number"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "name"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "Value"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
padding: 10, 5
size_hint: .5, 1
BoxLayout:
orientation: "horizontal"
spacing: 10, 10
size: 600, 50
size_hint: 1, None
Label:
text: "SN"
text_size: self.size
size_hint_x: .3
halign: "center"
ScrollView:
RowsExpense:
id: rowsExpense
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more2()
<rv>:
BoxLayout:
orientation: "vertical"
Button:
size_hint: .25, .03
text: "+Add"
on_press: root.add()
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
BoxLayout:
orientation: "vertical"
<ExtraPopup>:
title: " Extra"
title_size: 20
title_font: "Verdana"
size_hint: None, None
size: 400, 400
auto_dismiss: False
BoxLayout:
orientation: "vertical"
padding : 10, 5
spacing: 10, 10
BoxLayout:
orientation: "horizontal"
spacing: 10, 10
size: 550, 30
size_hint: 1, None
Label:
size_hint_x: .3
text: "SN"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .7
text: "Name"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
RowsExtra:
id: rowsExtra
BoxLayout:
orientation: "horizontal"
size_hint_x: .3
size_hint: .15, .1
Button:
text: "+Add More"
valign: 'bottom'
on_press: root.add_extra()
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size_hint: .5, .2
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
id: ok_text
on_release:
root.insert()
root.dismiss()
Button:
text: 'Cancel'
#size_hint_x: .5
on_release: root.dismiss()
<RowExtra>:
size_hint_y: None
height: self.minimum_height
height: 30
Button:
text: root.button_text
size_hint_x: .3
#top: 200
TextInput:
text: root.col_data[1]
size_hint_x: .7
<RowsExtra>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<RowsExpense>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<RowExpense>:
size_hint_y: None
height: self.minimum_height
height: 30
TextInput:
text: root.col_data[0]
multiline: False
<MenuButton#Button>:
text_size: self.size
valign: "middle"
padding_x: 5
size : (100, 40)
size_hint : (None, None)
background_color: 90 , 90, 90, 90
background_normal: ''
color: 0, 0.517, 0.705, 1
border: (0, 10, 0, 0)
<MainMenu>:
content_area: content_area
BoxLayout:
orientation: 'vertical'
spacing : 10
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size_hint_y: 2
MenuButton:
text: 'Menu'
size : (50, 12)
on_release: root.display()
BoxLayout:
id: content_area
size_hint_y: 30
You're calling class method while You should call instance method instead.
You need to store reference to Your RowsExpense instance in Your root class and run Your method through that reference. Then You can either pass that reference to the class through which You want to run the method as an argument in it's init function or use plain old:
App.get_running_app().root.whateverYouwanttodohere()
Related
I am struggling with referring to Labels on ScreenManager screens. I have a RecycleView and the class accumulates a total in the init. I would like to put this total on the screen outside the RecycleView. The id in the .kv file is t_pay. The total is accumulated in the Nq_rv class as self.total_bill. How do I take the total from this class and update the total field on the pay screen?
Note the total field at the bottom of this screenshot:
My main.py file is:
class Nq_rv(RecycleView):
def __init__(self, **kwargs):
super(Nq_rv, self).__init__(**kwargs)
bill_text = []
self.total_bill = 0.0
with open('bill.csv') as bill:
bill_reader = csv.reader(bill)
for row in bill_reader:
for item in range(len(row)):
if item < 2:
item_text = row[item]
else:
item_text = '{0:.2f}'.format(float(row[2]))
self.total_bill += float(row[2]) #total accumulation
text_row = {'text': item_text}
bill_text.append(text_row)
self.data = bill_text
#How do I update the t-pay field in the .kv file?
class Sm(ScreenManager):
total_pay = ObjectProperty() #I don't know if this is needed
def send_survey(self):
mypopup = MyPopup()
mypopup.show_popup('Survey', 'Survey sent!', 'OK!')
def pay(self):
mypopup = MyPopup()
mypopup.show_popup('Pay', 'Please put your card in the card reader and follow the prompts.', 'OK!')
def tip_slider_update(self):
self.ids.pay_screen.tip.text = '{0:.2f}'.format(float(self.ids.pay_screen.total_pay.text) * self.ids.pay_screen.tip_sldr.value)
def close_app(self):
App.get_running_app().stop()
class Pay_screen(Screen):
pass
class Survey_screen(Screen):
pass
class Finish_screen(Screen):
pass
class ImageButton(ButtonBehavior, Image):
pass
class Nq_button(Button):
pass
class MyPopup(Popup):
def show_popup(self, title_text, label_text, button_text):
mytext= label_text
content = BoxLayout(orientation="vertical")
content.add_widget(Label(text=mytext, font_size=20, text_size=(300, None)))
mybutton = Button(text="Ok!", size_hint=(1,.20), font_size=20)
content.add_widget(mybutton)
mypopup = Popup(content = content,
title = title_text,
auto_dismiss = False,
size_hint = (.5, .5))
mybutton.bind(on_press=mypopup.dismiss)
mypopup.open()
class nextqualApp(App):
icon = 'nextqual.png'
title = 'Pay / survey / join'
if __name__ == '__main__':
nextqualApp().run()
my .kv file is nextqual.kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
Sm:
id: sm
transition: FadeTransition()
Pay_screen:
id: pay_screen
manager: sm
Survey_screen:
id: survey_screen
manager: sm
<Nq_check_label#Label>:
markup: True
multiline: True
<Nq_check_items#Label>:
color: 0,0,0,1
<Nq_rv>:
viewclass: 'Nq_check_items'
RecycleGridLayout:
cols: 3
default_size: None, dp(20)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<Pay_screen>:
name: 'pay'
total_pay: t_pay
BoxLayout:
orientation: "vertical"
padding: 6
font_size: '24'
BoxLayout:
size_hint_y: None
height: "40dp"
Button:
text: "Pay your bill"
on_release: app.root.current = 'pay'
Button:
text: "Tell us how we did"
on_release: app.root.current = 'survey'
Button:
text: "I'm finished"
BoxLayout:
BoxLayout:
padding: 12
orientation: 'vertical'
BoxLayout:
height: "40dp"
size_hint_y: None
Label:
text: 'Table: 4'
Label:
text: 'Server: Julie'
Label:
text: 'Check # 58645'
BoxLayout:
canvas:
Color:
rgb: 255,255,255,255
Rectangle:
size: self.size
pos: self.pos
Nq_rv:
BoxLayout:
height: "30dp"
size_hint_y: None
Label:
text: 'Total check:'
size_hint_x: 75
#This is the field I want to update!
Label:
id: t_pay
text: '0.00'
halign: 'right'
size_hint_x: 25
<Survey_screen>:
name: "survey"
BoxLayout:
orientation: "vertical"
padding: 6
font_size: '24'
BoxLayout:
size_hint_y: None
height: "40dp"
Button:
text: "Pay your bill"
on_release: app.root.current = 'pay'
Button:
text: "Tell us how we did"
on_release: app.root.current = 'survey'
Button:
text: "I'm finished"
BoxLayout:
BoxLayout:
height: "100dp"
size_hint_y: None
Label:
size_hint_x: 40
Button:
size_hint_x: 20
text:"Send survey"
halign: "center"
on_press: app.root.send_survey()
Label:
size_hint_x: 40
embryo asked for some sample data. the file 'bill.csv' looks like this:
1,Seafood Sampler,15.99
1,Tea Smoked Duck,19.95
2,Shredded Duck with Ginger,22
1,Deli Rueben,9.95
1,Sam Adams,3
1,Cotswold Premium,4
1,Btl Pinot Noir,25
The idea of creating custom classes is to give you custom properties, for example Nq_rv is not only a RecycleView but a class that you can new properties, for example you can give the property total_bill that has the information of the total. That property will be accessible from the outside so you can make a binding with the text of t_pay:
*.py
class Nq_rv(RecycleView):
total_bill = NumericProperty(0.00) # <-- new property
def __init__(self, **kwargs):
super(Nq_rv, self).__init__(**kwargs)
self.load_data()
def load_data(self):
bill_text = []
total = 0.0
with open('bill.csv') as bill:
bill_reader = csv.reader(bill)
for row in bill_reader:
for item, val in enumerate(row):
if item < 2:
item_text = val
else:
item_text = '{0:.2f}'.format(float(val))
total += float(val) #total accumulation
text_row = {'text': item_text}
bill_text.append(text_row)
self.data = bill_text
self.total_bill = total # <-- update property
*.kv
BoxLayout:
canvas:
Color:
rgb: 255,255,255,255
Rectangle:
size: self.size
pos: self.pos
Nq_rv:
id: rv # <-- set id
BoxLayout:
height: "30dp"
size_hint_y: None
Label:
text: 'Total check:'
size_hint_x: 75
#This is the field I want to update!
Label:
id: t_pay
text: '{0:.2f}'.format(rv.total_bill) # <--- binding
halign: 'right'
size_hint_x: 25
I have two file test.py and test.kv .
i run test.py then shows show button.
When i click on show button then def abc call.Can someone tell me how to show array in dynamic label and value(Item1=5000.Item2=1000).
Item1 5000
Item2 1000
I am using array
arr = ({'Item1': 5000},{'Item2': 1000})
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
print(arr)
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Test().run()
test.kv
<Button#Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<Label#Label>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
Invoice:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
GridLayout:
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
Label:
size_hint_x: .35
text: "Item1"
text_size: self.size
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: "5000"
text_size: self.size
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
In your abc() method you can create labels and add them to your layout. In order to do that, I made a few change to your code. I added an id to your GridLayout and changed your custom label class to MyLabel and added it to the py file, so that I could create them in Python. Here is the modified Python file:
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class MyLabel(Label):
pass
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
layout = self.ids['invoices']
for invoice in arr:
for key,val in invoice.items():
lab1 = MyLabel(text=str(key),size_hint_x=.35, halign='left' )
lab2 = MyLabel(text=str(val),size_hint_x=.15, halign='right' )
layout.add_widget(lab1)
layout.add_widget(lab2)
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
And changes to the kv file included changing Label to MyLabel, moving as much as possible to the MyLabel class, and removing your example labels:
<Button#Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<MyLabel>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
text_size: self.size
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Invoice:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
GridLayout:
id: invoices
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
Although the option to iterate over the data and generate the widget dynamically is an option, the truth is that it is unbeatable in the long term. If you have structured information it is appropriate to use a design pattern and kivy offers to use a RecycleView for these cases, this implements the MVC pattern, so we just need to pass the data and establish a view where an appropriate adapter can be provided.
In your case it is enough to design a widget that is what is shown in each row:
<Item#GridLayout>:
cols: 2
text: "" # new property
value: 0 # new property
padding : 5, 0
spacing: 10, 0
Label:
size_hint_x: .35
text: root.text
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: str(root.value)
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
And then replace the GridLayout with the RecycleView:
RecycleView:
id: rv
viewclass: 'Item'
RecycleBoxLayout:
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
And in the event of the button assign the data, in this case you must convert your data to a list of dictionaries where the fields will be the text and value attribute of Item:
def convert_data(data):
l = []
for item in data:
for key, value in item.items():
l.append({'text': key, 'value': value})
return l
class Invoice(Screen):
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
# convert to [{'text': 'Item1', 'value': 5000}, {'text': 'Item2', 'value': 1000}]
self.rv.data = convert_data(arr)
Complete Code:
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
def convert_data(data):
l = []
for item in data:
for key, value in item.items():
l.append({'text': key, 'value': value})
return l
class Invoice(Screen):
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
# convert to [{'text': 'Item1', 'value': 5000}, {'text': 'Item2', 'value': 1000}]
self.rv.data = convert_data(arr)
class MyApp(App):
def build(self):
return Builder.load_file('test.kv')
if __name__ == '__main__':
MyApp().run()
test.kv
<Button#Button>:
font_size: 15
size_hint_y:None
height: 30
<Label#Label>:
font_size: 15
size_hint_y:None
height: 30
<Item#GridLayout>:
cols: 2
text: ""
value: 0
padding : 5, 0
spacing: 10, 0
Label:
size_hint_x: .35
text: root.text
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: str(root.value)
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Invoice:
rv: rv
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
BoxLayout:
RecycleView:
id: rv
viewclass: 'Item'
RecycleBoxLayout:
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
I have two file demo.py and demo.kv.
when i run demo.py after click on menu then shows +Add more button.When i click on +Add more button then three row add dynamic because i am using loop there.Every time add three row dynamic
But can anyone tell me when i add new row then how to remove previous three row?
Every time should be show only 3 new row and previous row should be delete.I am using code
def add_more(self):
self.remove_widget(Row())
for x in range(0, 3):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
demo.py
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.uix.popup import Popup
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Popup):
total_value = ObjectProperty(None)
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
def add_more(self):
self.ids.rows.add_more()
class Row(BoxLayout):
col_data = ListProperty(["?", "?", "?", "?", "?"])
name = ObjectProperty(None)
button_text = StringProperty("")
col_data3 = StringProperty("")
col_data4 = StringProperty("")
def __init__(self, **kwargs):
super(Row, self).__init__(**kwargs)
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_more()
def add_more(self):
self.remove_widget(Row())
for x in range(0, 3):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class rv(BoxLayout):
data_items = ListProperty([])
mode = StringProperty("")
def __init__(self, **kwargs):
super(rv, self).__init__(**kwargs)
def add(self):
self.mode = "Add"
popup = User()
popup.open()
class MainMenu(BoxLayout):
content_area = ObjectProperty()
def display(self):
self.rv = rv()
self.content_area.add_widget(self.rv)
class demo(App):
def build(self):
return MainMenu()
if __name__ == '__main__':
demo().run()
demo.kv
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
TextInput:
id : name
text: root.col_data3
width: 300
TextInput:
id: number_input
text: root.col_data4
width: 300
input_filter: 'int'
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<User>:
id: user
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Number"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "name"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "Value"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
<rv>:
BoxLayout:
orientation: "vertical"
Button:
size_hint: .25, .03
text: "+Add"
on_press: root.add()
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
BoxLayout:
orientation: "vertical"
<MenuButton#Button>:
text_size: self.size
valign: "middle"
padding_x: 5
size : (100, 40)
size_hint : (None, None)
background_color: 90 , 90, 90, 90
background_normal: ''
color: 0, 0.517, 0.705, 1
border: (0, 10, 0, 0)
<MainMenu>:
content_area: content_area
BoxLayout:
orientation: 'vertical'
spacing : 10
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size_hint_y: 2
MenuButton:
text: 'Menu'
size : (50, 12)
on_release: root.display()
BoxLayout:
id: content_area
size_hint_y: 30
remove_widget must receive as argument the instance of the child widget to be removed. Since you can get widget's children using its children attribute, to remove the previous three rows you can do the following:
def add_more(self):
if self.children:
for child in self.children[:3]:
self.remove_widget(child)
for x in range(0, 3):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
However, it's simpler to use clear_widgets method:
def add_more(self):
self.clear_widgets(self.children[:3])
for x in range(0, 3):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
Since you actually delete all the rows in the BoxLayout, you can do:
def add_more(self):
self.clear_widgets()
for x in range(0, 3):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
Edit:
To reset the index simply disregard self.row_count and use the value returned by range:
def add_more(self):
self.clear_widgets()
for x in range(1, 4):
self.add_widget(Row(button_text=str(x)))
I have two files demo.py and demo.kv
I have a button +Add More which add row dynamic.I am trying to add vertical scrollbar in dynamic row using ScrollView:.But its not working properly.
its mean when i add row in scrollview that row having extra space in scrollview i want add rows without any spacing.
ScrollView:
BoxLayout:
orientation: "horizontal"
size_hint_y: None
height: 500
Rows:
id: rows
demo.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class user(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return self.root
if __name__ == '__main__':
Test().run()
demo.kv
<Button#Button>:
font_size: 15
font_name: 'Verdana'
<Label#Label>:
font_size: 15
font_name: 'Verdana'
<TextInput#TextInput>:
font_size: 15
font_name: 'Verdana'
padding_y: 3
<Row>:
GridLayout:
cols: 2
row_force_default: True
row_default_height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
Button:
text: 'World 1'
width: 300
user:
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Test 1"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .8
text: "Test 2"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
BoxLayout:
orientation: "horizontal"
size_hint_y: None
height: 500
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size_hint: .5, .35
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
Button:
text: 'Cancel'
any help would be greatly appreciated.
If I have understood what you want, you have too many nested Layouts, that are unnecessary. Rows should be the main layout of your ScrollView.
On the other hand, Rows should always have the lowest possible height to contain their widgets (minimun_height property), not a fixed size.
Demo.py:
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class Test(App):
def build(self):
self.root = Builder.load_file('Demo.kv')
return self.root
if __name__ == '__main__':
Test().run()
Demo.kv:
<Button#Button>:
font_size: 15
font_name: 'Verdana'
<Label#Label>:
font_size: 15
font_name: 'Verdana'
<TextInput#TextInput>:
font_size: 15
font_name: 'Verdana'
padding_y: 3
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
Button:
text: 'World 1'
width: 300
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
User:
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Test 1"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .8
text: "Test 2"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size_hint: .5, .35
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
Button:
text: 'Cancel'
I am new to python/Kivy.
I have two files test.py and test.ky.
Now I am using two static row with serial number 1 and 2.
Can anyone tell me?
How to add row dynamic when click on '+add more' button.Now 2 row shows which are static row with serial number increment. I want add row dynamic 1 to 10 with serial number increment.
test.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (450, 525)
class display(Screen):
def add_more(self):
print('test')
class test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
test().run()
test.kv
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '1'
size_hint_x: .2
TextInput:
size_hint_x: .8
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '2'
size_hint_x: .2
TextInput:
size_hint_x: .8
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
Can someone help me?
You can make a custom class for Row and Rows, then have a method adding rows.
I modified your example a bit. Try this:
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.size = (450, 525)
class display(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class test(App):
def build(self):
self.root = Builder.load_string(KV)
return self.root
KV = """
<Row>:
orientation: "horizontal"
spacing: 0, 5
Button:
text: root.button_text
size_hint_x: .2
TextInput:
size_hint_x: .8
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
"""
test().run()