Display List of Ordereddict in Kivy - python

I have a list of Ordereddict as follows
list1= [OrderedDict([('Numbers', '15'), ('FirstName', 'John'), ('SecondName', 'Raul'), ('MiddleName', 'Kyle'), ('Grade', 22)]),
OrderedDict([('Names', 'John'), ('NewFirstName', 'Mark'), ('NewSecondName', 'Sachel'), ('NewThirdName', 'Raul'), ('Grade', 15)]),
OrderedDict([('Numbers', '25'), ('FirstName', 'Kyle'), ('SecondName', 'Venn'), ('MiddleName', 'Marcus'), ('Grade', 24)]),
OrderedDict([('Names', 'Sachel'), ('NewFirstName', 'Venn'), ('NewSecondName', 'Kyle'), ('NewThirdName', 'John'), ('Grade', 71)])]
There are 8 unique keys and one common key in it, i would like to create a table from it in kivy with the same order, with keys being the header of the table. My expected output is as below, i am new to kivy ecosystem and i dont see anything like tableview in that, any other views could be used to get this output and how
Expected output in kivy
I took the simpler recycyle view example given in the comment and edited the no of columns to 9 and tried picking the values from Ordereddict and i got the below output, since i am new to kivy i am not sure to pull the values as in expected output
Below are .py and .kv files
check.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
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 collections import OrderedDict
list1= [OrderedDict([('Numbers', '15'), ('FirstName', 'John'), ('SecondName', 'Raul'), ('MiddleName', 'Kyle'), ('Grade', 22)]),
OrderedDict([('Names', 'John'), ('NewFirstName', 'Mark'), ('NewSecondName', 'Sachel'), ('NewThirdName', 'Raul'), ('Grade', 15)]),
OrderedDict([('Numbers', '25'), ('FirstName', 'Kyle'), ('SecondName', 'Venn'), ('MiddleName', 'Marcus'), ('Grade', 24)]),
OrderedDict([('Names', 'Sachel'), ('NewFirstName', 'Venn'), ('NewSecondName', 'Kyle'), ('NewThirdName', 'John'), ('Grade', 71)])]
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 Button '''
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 RV(BoxLayout):
# data_items = ListProperty(newlist)
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
# create data_items
for i in list1:
self.data_items.append(i.values())
class TestApp(App):
title = "Kivy RecycleView & SQLite3 Demo"
def build(self):
return RV()
if __name__ == "__main__":
TestApp().run()
test.kv
#:kivy 1.10.0
<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()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 9
Label:
text: "Numbers"
Label:
text: "FirstName"
Label:
text: "SecondName"
Label:
text: "MiddleName"
Label:
text: "Grade"
Label:
text: "Names"
Label:
text: "NewFirstName"
Label:
text: "NewSecondName"
Label:
text: "NewThirdName"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 9
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'horizontal'
multiselect: True
touch_multiselect: True

Question - TableView
There are 8 unique keys and one common key in it, i would like to
create a table from it in kivy with the same order, with keys being
the header of the table.
Solution - Using Kivy RecycleView
Modify the app to extract the keys and values from the collections.OrderedDict
Add a class attribute of type ListProperty e.g. column_headings = ListProperty([])
Implement nested for loop to extract keys or column headings
Implement nested for loop to extract values
Override None with empty string
Snippets
class RV(BoxLayout):
column_headings = ListProperty([])
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
# extract keys or column headings
for row in list1:
for key in row.keys():
if key not in self.column_headings:
self.column_headings.append(key)
# extract values
values = []
for row in list1:
for key in self.column_headings:
try:
values.append(str(row[key]))
del row[key]
except KeyError:
values.append(None)
# replace None with empty string
self.data_items = ['' if x is None else x for x in values]
Output

Related

kivy: how can i have a recycleview display data unique to that instance

i have two instances of a recycleview managed buy a screen manager, but im struggling to have each instance display its unique data. they seem to share the data attribute. when i add a button to 'screen1' it shows up under 'screen2' instance as well. how do i direct the current instance to use the data unique to it? any help aprreciated thanks.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
kv = """
<ViewList>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
text: self.value
InputScreen:
name: 'input_screen'
id: inputscreen
MyReusableScreen:
name: 'screen1'
id: screen1
MyReusableScreen:
name: 'screen2'
id: screen2
<InputScreen>:
name: 'input_screen'
orientation: "vertical"
BoxLayout:
orientation: "vertical"
Button:
text: "first screen"
on_press: root.manager.current = 'screen1'
Button:
text: 'second screen'
on_press: root.manager.current = 'screen2'
<MyReusableScreen>:
name: 'mrs'
rv: rv
orientation: "vertical"
BoxLayout:
orientation: "vertical"
Label:
text: root.name
Button:
text: "add"
on_press: app.add_data('text')
Button:
text: "input screen"
on_press: root.manager.current = 'input_screen'
RV:
id: rv
viewclass: 'ViewList'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
"""
Builder.load_string(kv)
class ViewList(RecycleDataViewBehavior, Button):
def refresh_view_attrs(self, rv, index, data):
self.index = index
return super(ViewList, self).refresh_view_attrs(
rv, index, data)
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
class Root(ScreenManager):
pass
class MyReusableScreen(Screen):
def __init__(self, ** kwargs):
super(MyReusableScreen, self).__init__(**kwargs)
class InputScreen(Screen):
pass
class TestApp(App):
def build(self):
return Root()
def add_data(self, value):
sc = self.root.get_screen('screen1')
sc.ids.rv.data.insert(0, {'value': value} or 'default 1')
sc2 = self.root.get_screen('screen2')
sc2.ids.rv.data.insert(0, {'value': value or 'default 2'})
if __name__ == '__main__':
TestApp().run()
I adjusted some things to make your example run. First of all I added some things in your build method to see your InputScreen when the programm starts. Then I removed the value part, because for demonstration purposes it is only neccessary to see the switching default number when you switch between your screens. It looked like this:
class TestApp(App):
def build(self):
root = Root()
root.add_widget(InputScreen())
screen1 = MyReusableScreen(name='screen1')
screen2 = MyReusableScreen(name='screen2')
root.add_widget(screen1)
root.add_widget(screen2)
root.current = "input_screen"
return root
def add_data(self, value):
sc = self.root.get_screen('screen1')
sc.ids.rv.data.insert(0, {'value': 'default 1'})
sc2 = self.root.get_screen('screen2')
sc2.ids.rv.data.insert(0, {'value': 'default 2'})
And now the important part. You have to set a property in your viewclass in order to use the data value. As it is a string a StringProperty is what we are looking for. It should look like this.
class ViewList(RecycleDataViewBehavior, Button):
value = StringProperty("")
Another way would be to use the refresh_view_attrs method and set the button text to your new data. But then you have to change your initial kv string as self.value does not exist then.
KV
<ViewList>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
text: ""
Python
class ViewList(RecycleDataViewBehavior, Button):
def refresh_view_attrs(self, rv, index, data):
self.index = index
self.text = data['value']
return super(ViewList, self).refresh_view_attrs(
rv, index, data)

Kivy: Can't update text input value from another class

I'm new on kivy.I'm trying to change text input value (the string value that is shown in TextInput box) from another class, But nothing passes.
I have following widgets in class MyFirstScreen:
One RecycleView with multiple items (each item is a dictionary)
Two TextInputs
What I want to do: When each items in RecycleView selected, TextInputs should be update and load with corresponding values of selected item's dictionary.
But when i try to access current TextInput's value from another class (class SelectableLabel):
class SelectableLabel(RecycleDataViewBehavior, Label):
#...
def update_text_inputs(self, *kwarg):
my_text_input = MyFirstScreen().ids.system_name_text_input_id #<--i can access to widget
print("my_print_val is:", my_text_input.text) #<--but widget's current text value is : ''
my_text_input.text = "Updated Value"
I can access to my_text_input widget but its text (my_text_input.text) is an empty string ('').Furthermore when i change the value of my_text_input.text, nothing happens in TextInput's box.
Does anyone know what am I doing wrong here or how to make this work? Thank you in advance...
Here is my .py code:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
class Manager(ScreenManager):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class MyFirstScreen(Screen):
system_name_text_input_id = ObjectProperty(None)
def __init__(self, **kwarg):
super().__init__(**kwarg)
print("__init__ of MyFirstScreen is Called")
def get_text_inputs(self):
ret_val = self.ids.system_name_text_input_id.text
print("get_text_input is called, ret_val:", ret_val)
return ret_val
class RecycleViewWidget(RecycleView):
def __init__(self, **kwargs):
super(RecycleViewWidget, self).__init__(**kwargs)
self.items_of_rv = []
for i in range(1, 21):
self.items_of_rv.append(
{"color": (0, 0, 0, 1), "font_size": "20", "text": f"User {i}",
"user_id": f"{100 * i}"})
self.data = [item for item in self.items_of_rv]
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
""" Adds selection and focus behaviour to the view. """
class SelectableLabel(RecycleDataViewBehavior, Label):
""" 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(SelectableLabel, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
""" Add selection on touch down """
if super(SelectableLabel, 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 = not is_selected
if is_selected:
rv.data[index].update({'color': (1, 1, 1, 1)})
self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
print("selection changed to {0}".format(rv.data[index]))
self.update_text_inputs()
else:
if rv.data[index].get("color") == (1, 1, 1, 1):
rv.data[index].update({'color': (0, 0, 0, 1)})
self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
self.selected = not self.selected
def update_text_inputs(self, *kwarg):
my_text_input = MyFirstScreen().ids.system_name_text_input_id#<--i can access to widget
print("my_print_val is:", my_text_input.text)#<--but widget's current text value is : ''
# my_text_input.text = "Updated Value"
main_style = Builder.load_file("test.kv")
class MyApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return main_style
if __name__ == '__main__':
MyApp().run()
And my .kv code:
Manager:
MyFirstScreen:
<SelectableLabel>:
canvas.before:
Color:
rgba: (0, 0, 1, 1) if self.selected else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
<RecycleViewWidget>:
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<MyFirstScreen>:
name: 'system_setup_page'
system_name_text_input_id:system_name_text_input_id
GridLayout:
cols: 2
BoxLayout:
cols: 1
padding: 20
RecycleViewWidget:
FloatLayout:
Label:
size_hint: None, None
text: "Name:"
font_size: 22
pos_hint: {'center': (20/100, 90/100)}
TextInput:
id: system_name_text_input_id
size_hint: None, None
hint_text: "Type Your Name..."
size: 200, 30
multiline: False
pos_hint: {'center': (65/100, 90/100)}
on_text: root.get_text_inputs()
Label:
size_hint: None, None
text: "User ID:"
font_size: 20
pos_hint: {'center': (20/100, 70/100)}
TextInput:
size_hint: None, None
size: 200, 30
hint_text: "Type Your ID..."
pos_hint: {'center': (65/100, 70/100)}
Problem is because using MyFirstScreen() in update_text_inputs() you create new instance of class MyFirstScreen but you have to use existing instance.
It should be better way to get it but at this moment my only idea is to use parent for this .
Because there are many widgets between these elements so it needs many parent:
my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id
I found it using print(self.parent), next print(self.parent.parent), etc.
def update_text_inputs(self, *kwarg):
#print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id)
#print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id.text)
my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id
print("my_print_val is:", my_text_input.text)
my_text_input.text = "Updated Value"

Listing Order Numbers, Items and Subitems from database

So, I'm trying to create a list that pulls from a mysql database that displays an order # as a button and a new window expands to display the order numbers items/subitems with checkboxes to have checked when an item is selected. I have the window to pop up; however, nothing populates and my query prints out information/list. After all boxes are checked and a Finish button is clicked on, it will remove the order from the list to show it has been worked on. I found this on the forums; however, it's not pulling anything for me:
How to fetch data from database and show in table in kivy+python
Thank you!
main.py
import pymysql
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
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
orderNum = "1"
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 Button '''
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 RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_order()
def get_order(self):
connection = pymysql.connect(host='localhost', user='root',passwd='password', db='Shop')
cursor = connection.cursor()
cursor.execute("SELECT itemName, ITEM FROM order_list WHERE orderID=%s", (orderNum,))
rows = cursor.fetchall()
# create data_items
for row in rows:
for col in row:
self.data_items.append(col)
class TestApp(App):
title = "Kivy RecycleView & pymysql Demo"
def build(self):
return RV()
if __name__ == "__main__":
TestApp().run()
kivy.kv
#:kivy 1.10.0
<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: "Finish"
on_release:
root.obj.update_changes(txtinput.text)
root.dismiss()
Button:
size_hint: 1, 0.2
text: "Cancel Changes"
on_release: root.dismiss()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 2
Label:
text: "Order Number"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 2
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
Here's my list that pulls information and uses a print function:
('Sub', 'Italian')
('Sub', 'Meatball')
('Drink', 'Apple Juice')
('Side', 'Salad')
('Soup', 'Chicken and rice')
What I have and What I'm Trying to Achieve

Change variable via selected item in Kivy

So I learning Kivy but I am stuck with the ListView or, as the ListView seems to be deprecated, the RecycleView.
My problem is that I want the label with species_text as ID to change based on the item I click on, once in the label is in view.
The documentation helped me as far as making the SelectableLabel and being able to click / color it, but I do not know how to change the text of species_text via the data list of the RecycleView or how to save the data list in the ScreenTest class.
Here is my code:
from kivy.app import App
from kivy.uix.button import Label, Button
from kivy.lang import Builder
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_string("""
<ScreenTest>:
Label:
pos_hint: {"x": .45, "top": 1}
text: "Headline"
size_hint: .1, .1
BoxLayout:
pos_hint: {"x": 0.02, "top": .8}
RecycleView:
id: species_list_view
data: [{'name': "Species1", "text": "S1"}, {'name': "Species2", "text": "S2"}]
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
orientation: 'vertical'
multiselect: False
touch_multiselect: False
Label:
id: species_text
text: "Speciestext"
BoxLayout:
size_hint_y: None
height: 30
spacing: 10
canvas:
Color:
rgba: .5, .2, .1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
text: "Go Back"
Button:
text: "Next"
<SelectableLabel>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
""")
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
pass
class SelectableLabel(RecycleDataViewBehavior, Label):
''' 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(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, 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:
print("selection changed to {0}".format(rv.data[index]))
else:
print("selection removed for {0}".format(rv.data[index]))
class ScreenTest(Screen):
pass
screen_manager = ScreenManager()
screen_manager.add_widget(ScreenTest(name="screen_test"))
class TestApp(App):
def build(self):
return screen_manager
test_app = TestApp()
test_app.run()
Thanks for your help!
The apply_selection() method has RecycleView arguments, taking into account that we can create a property that has the selected text, and then we make a bind with the text of the Label:
...
RecycleView:
id: species_list_view
data: [{'name': "Species1", "text": "S1"}, {'name': "Species2", "text": "S2"}]
viewclass: 'SelectableLabel'
text_selected: "" # create property
SelectableRecycleBoxLayout:
...
Label:
id: species_text
text: "Speciestext" if not species_list_view.text_selected else species_list_view.text_selected # apply binding
...
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
print("selection changed to {0}".format(rv.data[index]))
rv.text_selected = rv.data[index]['text'] # set text
else:
print("selection removed for {0}".format(rv.data[index]))
When you select the SelectableLabel you must find the "species_text" Label and change its text.
One way to do that is from its "apply_selection" method.
if is_selected:
for screen in App.get_running_app().root.screens:
if screen.name == "screen_test":
screen.ids.species_text.text = rv.data[index]["name"]
P.S. There is a typo in the kv code:
The "touch_multiselect" attribute is written "touc_multiselect"

How to run python script from another .py file and show in current window

menu.py
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.lang import Builder
class CustDrop(DropDown):
def __init__(self, **kwargs):
super(CustDrop, self).__init__( **kwargs)
self.select('')
kv_str = Builder.load_string('''
BoxLayout:
orientation: 'vertical'
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
Color:
rgb: (1,1,1)
size_hint_y:1
Button:
id: btn
text: 'user'
on_release: dropdown.open(self)
#size_hint_y: None
#height: '48dp'
CustDrop:
id: dropdown
Button:
text: 'List User'
size_hint_y: None
height: '48dp'
Label:
size_hint_x: 4
Label:
size_hint_y: 9
''')
class ExampleApp(App):
def build(self):
return kv_str
if __name__ =='__main__':
ExampleApp().run()
user.py
import kivy
kivy.require('1.9.0') # replace with your current kivy version !
import sqlite3 as lite
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty,NumericProperty
from kivy.lang import Builder
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
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 kivy.core.window import Window
Window.size = (500, 500)
#con = lite.connect('user.db')
#con.text_factory = str
#cur = con.cursor()
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Button '''
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,*args):
popup = TextInputPopup(self)
popup.open()
def update_changes(self):
self.text = txt
class RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
# cur.execute("SELECT * FROM `users` order by id asc")
# rows = cur.fetchall()
rows = [(1, 'Yash', 'Chopra'),(2, 'amit', 'Kumar')]
for row in rows:
for col in row:
self.data_items.append(col)
class ListUser(App):
title = "Users"
def build(self):
self.root = Builder.load_file('user.kv')
return RV()
if __name__ == '__main__':
ListUser().run()
user.kv
#:kivy 1.10.0
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
text: "ID"
Label:
text: "First Name"
Label:
text: "Last Name"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 3
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
I have two file menu.py and user.py. menu.py file show menu and user.py shows list of user..
when i run menu.py then shows user menu on top .When i click on user then 'list user' show(submenu of user).When i click on 'list user' then user list should show in current window.Menu will be on top and user-list show in same window(under menu).
To dsiplay the user list in the same window, combine both Python scripts and kv files into one. Please refer to the example below for details.
Example
mainmenu.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
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
import sqlite3 as lite
dbPath = "/home/iam/dev/SQLite/sampleDB/ChinookDB/"
#con = lite.connect('user.db')
con = lite.connect(dbPath + "chinook.db")
#con.text_factory = str
cur = con.cursor()
class MessageBox(Popup):
obj = ObjectProperty(None)
obj_text = StringProperty("")
def __init__(self, obj, **kwargs):
super(MessageBox, 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 Button '''
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 = MessageBox(self)
popup.open()
def update_changes(self, txt):
self.text = txt
class RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
cur.execute("SELECT CustomerId, FirstName, LastName FROM 'customers' order by CustomerId asc")
rows = cur.fetchall()
for row in rows:
for col in row:
self.data_items.append(col)
class CustDrop(DropDown):
def __init__(self, **kwargs):
super(CustDrop, self).__init__(**kwargs)
self.select('')
class MainMenu(BoxLayout):
users = ObjectProperty(None)
dropdown = ObjectProperty(None)
def display_users(self):
# rv = RV()
self.dropdown.dismiss()
self.users.add_widget(RV())
class MainMenuApp(App):
title = "Example"
def build(self):
return MainMenu()
if __name__ == '__main__':
MainMenuApp().run()
mainmenu.kv
#:kivy 1.10.0
<MessageBox>:
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()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
text: "ID"
Label:
text: "First Name"
Label:
text: "Last Name"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 3
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
<MainMenu>:
users: users
dropdown: dropdown
orientation: 'vertical'
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
Color:
rgb: (1,1,1)
size_hint_y:1
Button:
id: btn
text: 'user'
on_release: dropdown.open(self)
CustDrop:
id: dropdown
Button:
text: 'List User'
size_hint_y: None
height: '48dp'
on_release: root.display_users()
Label:
size_hint_x: 4
text: "label 1"
BoxLayout:
id: users
size_hint_y: 9
Output

Categories

Resources