Kivy, RecycleView Add and Delete rows - python

I'm trying to better understand how the RecycleView functions. Seems like only practical examples will teach me. Docs aren't helping. Kindly have a look at my current screen in the pic below.
Now following are what I'm trying to achieve.
Add/Remove new rows to/from the list.
The first column sl/no should maintain the order even after deleting from in between.
How to achieve 'sort' function? Is it by taking the data into python and do the sort and then update that to the RV again ?
Please find the both .py and .kv codes below.
rv_main.py
import os
os.environ['KIVY_GL_BACKEND'] = 'gl'
import kivy
kivy.require('1.11.0')
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.properties import ListProperty, BooleanProperty
from kivy.properties import NumericProperty
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
#-----------------------------------------------------------------------
class RecycleViewRow(RecycleDataViewBehavior, BoxLayout):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
slno = StringProperty('')
typ = StringProperty('')
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(RecycleViewRow, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(RecycleViewRow, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
pass
else:
pass
def delete_row(self,rv, index, is_selected):
if is_selected:
rv.data.pop(index)
rv.layout_manager.clear_selection()
#-----------------------------------------------------------------------
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
#fetch data from the database
self.data = [{'slno': str(x+1),'typ': 'default'} for x in range(4)]
#-----------------------------------------------------------------------
class DataTable(BoxLayout):
def addRow(self):
pass
def removeRow(self):
pass
#-----------------------------------------------------------------------
class RvMainApp(App):
def build(self):
return DataTable()
if __name__ == '__main__':
RvMainApp().run()
rvmain.kv
#: kivy 1.11.0
<RecycleViewRow>:
id: rv
slno: ""
typ: ""
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0.4, 0.4, 0.4, 1)
Rectangle:
pos: self.pos
size: self.size
orientation: 'horizontal'
size_hint: 1.0, 1.0
Label:
text: root.slno
size_hint_x : 1.0
Label:
text: root.typ
size_hint_x : 1.0
#----------------------------------------------------------------
<RV>:
id : rv
viewclass: 'RecycleViewRow'
SelectableRecycleBoxLayout:
default_size: None, dp(40)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
#----------------------------------------------------------------
<DataTable>:
orientation : 'vertical'
Button:
BoxLayout:
Button:
RV:
Button:
BoxLayout:
Button:
text: "Add"
on_release: rv.data.append({"slno": "?", "typ": 'default'})
Button:
text: "Remove"
on_release:

You edit the data list of the recycleview. The data will be sorted as it is sorted in that list.
So here is an example of the add remove feature:
from kivy.app import App
from kivy.lang import Builder
KV = '''
<Row#BoxLayout>:
ind: 1
Button:
text: str(root.ind)
Button:
text: "default"
BoxLayout:
ind: 1
orientation: "vertical"
Button:
BoxLayout:
Button:
RecycleView:
id: rv
data: [{"text":"first","ind":1}]
viewclass: 'Row'
RecycleBoxLayout:
default_size_hint: 1, None
default_size: None, dp(56)
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Button
BoxLayout:
Button:
text: "Add"
on_release:
root.ind += 1
rv.data.append({"ind": root.ind})
Button:
text: "Remove"
on_release:
root.ind = root.ind - 1 if root.ind > 0 else 0
if len(rv.data): rv.data.pop(-1)
'''
class Test(App):
def build(self):
self.root = Builder.load_string(KV)
return self.root
Test().run()
And here is an example on how to sort the data list by some key. In this case ind.
from kivy.app import App
from kivy.lang import Builder
KV = '''
RecycleView:
viewclass: 'Label'
data: sorted([{"text":"!", "ind":3},{"text":"world", "ind":2},{"text":"hello", "ind":1}], key=lambda k: k["ind"])
RecycleBoxLayout:
id: layout
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
'''
class TestApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == '__main__':
TestApp().run()

Related

MDExpansionPanel doesn't behave very well in a RecycleView Python/Kivy

For some reason MDExpansionPanel doesn't behave as it should in a RecycleView, each time you expand the list, the more it deviates from the pattern. I don't know if there is something wrong with my code or the MDExpansionPanel was not made for a RecycleView
main.py
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import (MDExpansionPanel,
MDExpansionPanelOneLine)
Builder.load_string("""
<MyRecycleView>:
viewclass: "MyExpansionPanel"
effect_cls: "ScrollEffect"
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: dp(10)
<Content>:
adaptive_height: True
IconLeftWidget:
icon: "account"
""")
class MyRecycleView(RecycleView):
pass
class Content(MDBoxLayout):
pass
class MyExpansionPanel(MDExpansionPanel, RecycleDataViewBehavior):
text = StringProperty()
def __init__(self, **kwargs):
self.panel_cls = MDExpansionPanelOneLine()
super().__init__(**kwargs)
def refresh_view_attrs(self, rv, index, data):
self.panel_cls.text = data["text"]
return super().refresh_view_attrs(rv, index, data)
class MyApp(MDApp):
def build(self):
recycle = MyRecycleView()
recycle.data = [
{
"icon":"arrow-right",
"text":"Test",
"content":Content()
}for _ in range(5)
]
return recycle
MyApp().run()
Result:
Any idea how to resolve this?

How can display data from the database to kivy table

I want to display a table in one of the screen and the displayed data in the table should come from the loan database, loan table.
I have created the database and also there is no error which is being shown. The table is created but there is no data displayed on it.Its empty table.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
import json
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from loandatabase import Database
database = Database()
Builder.load_file('design.kv')
class MainScreen(Screen):
def goto_admin_page(self):
self.manager.current = "adminfirst_screen"
def goto_agent_page(self):
pass
def goto_customer_page(self):
pass
class AdminScreenFirst(Screen):
def go_to_adminsecond(self,uname,pword):
with open("users.json") as file:
users =json.load(file)
if uname in users and users[uname]['password'] == pword:
self.manager.current = "adminsecond_screen"
else:
self.ids.login_wrong.text = "Invalid Credentials.Please Contact the administrator"
class AdminScreenSecond(Screen):
def go_to_adminpending(self):
self.manager.current = "adminPending_screen"
def go_to_adminapproved(self):
self.manager.current = "adminsecond_screen"
def go_to_adminrejected(self):
self.manager.current = "adminsecond_screen"
class AdminPendingScreen(Screen):
def display(self):
self.manager.current = "rv_screen"
class RV(Screen):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
for row in database.view():
for col in row:
self.data_items.append(col)
class TextInputPopup(Popup):
obj = ObjectProperty(None)
obj_text = StringProperty("")
def __init__(self, obj, **kwargs):
super(TextInputPopup, self).__init__(**kwargs)
self.obj = obj
self.obj_text = obj.text
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
def on_press(self):
popup = TextInputPopup(self)
popup.open()
def update_changes(self, txt):
self.text = txt
class RootWidget(ScreenManager):
pass
class MainApp(App):
def build(self):
return RootWidget()
if __name__ == "__main__":
MainApp().run()
my kivy code :
<MainScreen>:
GridLayout:
cols:1
GridLayout:
cols:1
padding:15,15
spacing:20,20
Label:
text:"Login"
font_size:"20sp"
Button:
text:"Admin"
on_press : root.goto_admin_page()
Button:
text:"Agent"
on_press : root.goto_agent_page()
Button:
text: "Customer"
on_press:root.goto_customer_page()
<AdminScreenFirst>:
GridLayout:
cols:1
padding:15,15
spacing:20,20
Label:
text:"Admin Login"
font_size:"20sp"
TextInput:
id:username
hint_text:"Username"
TextInput:
id:password
password:True
hint_text:"Password"
RelativeLayout:
Button:
text:"Login"
on_press : root.go_to_adminsecond(root.ids.username.text,root.ids.password.text)
size_hint :0.3,0.5
pos_hint: {'center_x' : 0.5 , 'center_y' : 0.6}
Label:
id:login_wrong
text:""
<AdminScreenSecond>:
GridLayout:
cols:1
padding:15,15
spacing:20,20
Label:
text:"Loan"
font_size:"20sp"
Button:
text:"Pending Request"
on_press:root.go_to_adminpending()
Button:
text:"Approved"
on_press: root.go_to_adminapproved()
Button:
text:"Rejected"
on_press: root.go_to_adminrejected()
<AdminPendingScreen>:
GridLayout:
cols:1
padding:15,15
spacing:20,20
Label:
text:"Loans"
Button:
text:"Display"
on_press: root.display()
Label:
id:display
text:""
<TextInputPopup>:
title: "Popup"
size_hint: None, None
size: 400, 400
auto_dismiss: False
BoxLayout:
orientation: "vertical"
TextInput:
id: txtinput
text: root.obj_text
Button:
size_hint: 1, 0.2
text: "Save Changes"
on_release:
root.obj.update_changes(txtinput.text)
root.dismiss()
Button:
size_hint: 1, 0.2
text: "Cancel Changes"
on_release: root.dismiss()
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 11
Label:
text: "LoanID"
Label:
text: "Name"
Label:
text:"Tenure"
Label:
text:"Balance"
Label:
text:"LoanType"
Label:
text:"InterestType"
Label:
text:"Interest % p.a."
Label:
text:"Security"
Label:
text:"Total"
Label:
text:"EMI"
Label:
text:"Request"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 11
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
#orientation: 'vertical'
multiselect: True
touch_multiselect: True
<RootWidget>:
MainScreen:
name:"mainfirst_screen"
AdminScreenFirst:
name:"adminfirst_screen"
AdminScreenSecond:
name:"adminsecond_screen"
AdminPendingScreen:
name:"adminPending_screen"
RV:
name:"rv_screen"
my database code:
import sqlite3
class Database:
def __init__(self):
self.conn = sqlite3.connect("loandatabase.db")
self.cur = self.conn.cursor()
self.cur.execute("CREATE TABLE IF NOT EXISTS loan (id INTEGER PRIMARY KEY, customer_name TEXT, tenure integer, balance integer, loantype TEXT, interesttype TEXT,interest integer,security TEXT,totalpayment integer,emi integer,instruction TEXT)")
self.conn.commit()
def insert(self,cname,tenure,blance,ltype,itype,interest,security,tpay,emi,instr):
self.cur.execute("INSERT INTO loan VALUES (NULL,?,?,?,?,?,?,?,?,?,?)",(cname,tenure,blance,ltype,itype,interest,security,tpay,emi,instr))
self.conn.commit()
def view(self):
self.cur.execute("SELECT * FROM loan")
rows = self.cur.fetchall()
return rows
def __del__(self):
self.conn.close()
[![enter image description here][1]][1]
I would request you to help me with it. Thank You in Advance
I am using Kivy,Python,sqlite3
This is displayed:
[1]: https://i.stack.imgur.com/fkUvS.png
Try this:
class MainApp(App):
title = 'Title of the app'
def build(self):
sm = ScreenManager('''You can add transition here''')
sm.add_widget(MainScreen(name='main'))
sm.add_widget(AdminScreenFirst(name='admin1'))
sm.add_widget(AdminScreenSecond(name='admin2'))
sm.add_widget(AdminPendingScreen(name='pending'))
sm.add_widget(RV(name='rv'))
return sm

Kivy RecycleView. How to refresh the screen after deleting data

What i'm trying to do is find a way to refresh a table made by using recycleview,
If you press one of the label created, my code delete data from table, but not refresh the table on a graphic level
Obviously if you press the same label 2 times, python gives ValueError...
Here's my code:
temp.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.properties import ListProperty
class Sfondo_tabella(RecycleDataViewBehavior, Label):
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos) and self.selectable:
x = Screen_1()
x.remove(self.text)
class Screen_1(Screen):
data_items = ListProperty([])
data_items = ['1', '2', '3']
def remove(self, data):
self.data_items.remove(data)
class TempApp(App):
pass
if __name__ == '__main__':
TempApp().run()
temp.kv
ScreenManager:
id: screen_manager
name: "screen_manager"
Screen_1:
id: screen_1
name: "Screen_1"
manager: screen_manager
<Sfondo_tabella>:
# Draw a background to indicate selection
color: 0,0,0,1
font_size: self.height * 0.5
text_size: self.width, None
valign: 'top'
halign: 'center'
canvas.before:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
canvas:
Color:
rgba:0,0,0,1
Line:
width:0.5
rectangle:(self.x,self.y,self.width,self.height)
<Screen_1>:
BoxLayout:
RecycleView:
viewclass: 'Sfondo_tabella'
data: [{'text': str(x)} for x in root.data_items]
RecycleGridLayout:
cols: 10
size_hint: 1, None
default_size: None, dp(20)
default_size_hint: 1, None
height: self.minimum_height
width: self.minimum_width
In your code you are not updating the RecycleView data. The refresh_view_attrs function should be overloaded to get the index of the label clicked/touched upon and then the data needs to be updated accordingly. Following is the updated code for temp.py:
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.properties import ListProperty
class Sfondo_tabella(RecycleDataViewBehavior, Label):
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
self.index = index
return super(Sfondo_tabella, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos) and self.selectable:
x = Screen_1()
x.remove(self.text)
self.parent.parent.data.pop(self.index)
class Screen_1(Screen):
data_items = ListProperty([])
data_items = ['1', '2', '3']
def remove(self, data):
self.data_items.remove(data)
class TempApp(App):
pass
if __name__ == '__main__':
TempApp().run()
This will update properly the data of RecycleView and the GUI accordingly.

Passing data to refresh_view_attrs. Python. Kivy

How can I pass data from RequestRecycleView to refresh_view_data? I tried with global variables and instantiating data in RequestRecycleView but still can't trigger refresh_view_data by appending Observable data. It is working when I return RequestRecycleView as root but I want ScreenManager to be my root.
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
from random import sample
from string import ascii_lowercase
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
kv = """
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManager:
transition: FadeTransition()
RequestsScreen:
<RequestRow#BoxLayout>
size_hint_y: None
orientation: 'vertical'
row_index: id_row_index.text
row_index:''
pos: self.pos
size: self.size
Label:
id: id_row_index
text: root.row_index
<RequestRecycleView#RecycleView>:
#id: rv
viewclass: 'RequestRow'
SelectableRecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
<RequestsScreen>
name: 'RequestsScreen'
BoxLayout:
orientation: 'vertical'
Label:
text: 'recycle'
RequestRecycleView:
"""
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
class RequestRow(RecycleDataViewBehavior):
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
self.row_index = str(index)
self.row_content = data['text']
return super(RequestRow, self).refresh_view_attrs(
rv, index, data)
class ScreenManagement(ScreenManager):
pass
class RequestRecycleView(RecycleView):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.data = []
for r in range(30):
row = {'text': ''.join(sample(ascii_lowercase, 6))}
self.data.append(row)
class RequestsScreen(Screen):
pass
Builder.load_string(kv)
sm = ScreenManagement()
sm.add_widget(RequestsScreen(name = 'requests'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
By modifying
<RequestRow#BoxLayout>
size_hint_y: None
orientation: 'vertical'
row_index: id_row_index.text
row_index:''
pos: self.pos
size: self.size
Label:
id: id_row_index
text: root.row_index
to
<RequestRow#BoxLayout>
text: 'abba'
size_hint_y: None
orientation: 'vertical'
row_index: id_row_index.text
row_index:''
pos: self.pos
size: self.size
Label:
id: id_row_index
text: self.parent.text
results in working code. Note that the dictionary keys in the data are expected to be attributes of the viewclass. The added text attribute in RequestRow, provides that attribute, and the text: self.parent.text in the Label places that text (from the viewclass) into the Label. Also, you can replace the lines:
Builder.load_string(kv)
sm = ScreenManagement()
sm.add_widget(RequestsScreen(name = 'requests'))
with just:
sm = Builder.load_string(kv)
since your kv file specifies the ScreenManager as the root object.

Unknown class error even if class is defined Kivy/recycle view

I have this snippet from my design.kv file:
<Track>:
on_release:
root.print_data(self.text)
RecycleView:
viewclass: 'Track'
RecycleGridLayout:
cols: 1
default_size_hint: 1, None
orientation: 'vertical'
However it returns an error:
The class 'Track was defined as seen in the snippet above as well as in my python code.
I tried setting the viewclass to 'Button' and it worked but it just returned a button which is not the intended behavior.
What am I getting wrong here?
Thanks :)
The whole code of my python and kivy files are right here: https://github.com/Jezrianne/ANTS
Just in case the error does not originate from the snippet above :)
Root Widget - Screen
The following example illustrates using Screen widget as the root widget and combined with RecycleView widget.
main.py
from kivy.app import App
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<Track>:
on_release:
root.print_data(self.text)
<RootWidget>:
RecycleView:
id: rv
viewclass: 'Track'
SelectableRecycleGridLayout:
cols: 1
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
''')
class Track(RecycleDataViewBehavior, Button):
def print_data(self, text):
print("\nprint_data: text=", text)
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class RootWidget(Screen):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.ids.rv.data = [{'text': str(x)} for x in range(100)]
class TestApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
TestApp().run()
Root Widget - RecycleView
There is no attribute, orientation: for GridLayout. Please remove it from your kv file.
You need to implement the following:
Snippet
class Track(RecycleDataViewBehavior, Button):
def print_data(self, text):
print("\nprint_data: text=", text)
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
Example
main.py
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.button import Button
class Track(RecycleDataViewBehavior, Button):
def print_data(self, text):
print("\nprint_data: text=", text)
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'text': str(x)} for x in range(100)]
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()
test.kv
#:kivy 1.11.0
<Track>:
on_release:
root.print_data(self.text)
<RV>:
viewclass: 'Track'
SelectableRecycleGridLayout:
cols: 1
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Output

Categories