Bind to is_selected of ListItemButton

77 views
Skip to first unread message

Jonas Zimmermann

unread,
Feb 3, 2016, 3:31:48 PM2/3/16
to kivy-...@googlegroups.com
Hi,

I just tried to extend the example widgets/lists/list_master_detail.py by creating a subclass of ListItemButton and binding to ‘is_selected’:

class ClientListItemButton(ListItemButton):
def __init__(self, *args, **kwargs):
super(ClientListItemButton, self).__init__(*args, **kwargs)
self.fbind('on_is_selected', self.print_info)
self.fbind('on_press', self.print_info)

def print_info(self,*args):
print "item {}, is_selected: {}, index: {}".format(self, self.is_selected, self.index)

as expected, print_info gets fired ‘on_press’, but not ‘on_is_selected’. Looking at the source in listview.py, SelectableView only inherits from object. Is this the reason no events are fired by changes to is_selected? Why would that be the case?

Thanks,
Jonas

Jonas Zimmermann

unread,
Feb 3, 2016, 4:24:57 PM2/3/16
to Kivy users support
Also, SelectableView is defined both in kivy/uix/selectableview.py and in kivy/uix/listview.py, but only the latter seems to ever be used (other than in examples/widgets/lists/list_kv.py). Point in case to remove kivy/uix/selectableview.py?

Jonas

ZenCODE

unread,
Feb 4, 2016, 3:49:39 PM2/4/16
to Kivy users support
Hi Jonas

The inheriting from object is not the problem (but a good guess to be fair). As long as there is an object that inherits from an EventDispatcher somewhere in the hierarchy of superclasses, the property bindings should work.

As for SelectableView being defined twice, by jove you're right. And they appear identical, so it must be just an over-sight. I'll prepare a pull request to fix that, but you're welcome to try and beat me to it :-). Keep in mind any change should not break compatibility i.e. both imports should be valid, but just use a single definition.

As for the 'is_selected' property, my knowledge is a bit rusty here, but the docs say it 'should be kept in sync with the equivalent property in the data item it represents.', implying it's not automatic. It could be the work of the adapter. Have you checked out the 'propagate_selection_to_data' property of the adapter? Is that set to True in your example?

I would try to run it but I don't see a 'ClientListItemButton' in the example you mention, so you're probably running significantly modified code? Perhaps post if you don't come right...:-)

Good luck + thanks


Jonas Zimmermann

unread,
Feb 4, 2016, 11:33:46 PM2/4/16
to kivy-...@googlegroups.com
Hi Richard,
PR submitted (https://github.com/kivy/kivy/pull/3975 )


> On 4 Feb 2016, at 15:49, ZenCODE <zenkey....@gmail.com> wrote:
>
> Hi Jonas
>
> The inheriting from object is not the problem (but a good guess to be fair). As long as there is an object that inherits from an EventDispatcher somewhere in the hierarchy of superclasses, the property bindings should work.
[…]
> As for the 'is_selected' property, my knowledge is a bit rusty here, but the docs say it 'should be kept in sync with the equivalent property in the data item it represents.', implying it's not automatic. It could be the work of the adapter. Have you checked out the 'propagate_selection_to_data' property of the adapter? Is that set to True in your example?

The docs for listadpter are pretty clear in stating that propagate_selection_to_data only pertains to data, because 'only the item view for a given data item is selected/deselected as part of the maintained selection list’. Indeed, the ‘is_selected’ property is automatically updated as you can verify with the following self-contained example. I you click button ‘B’ twice, you will get the following output (one line per click):
on_press: item <ClientListItemButton text=B>, is_selected: False, index: 1
on_press: item <ClientListItemButton text=B>, is_selected: True, index: 1
So when the second click happens, is_selected is true…
Example:


from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.listview import ListView, ListItemButton
from kivy.adapters.dictadapter import DictAdapter

fruit_data = {'1':{'name':'A'}, '2':{'name':'B'}}
class ClientListItemButton(ListItemButton):
def __init__(self, *args, **kwargs):
super(ClientListItemButton, self).__init__(*args, **kwargs)
self.fbind('on_is_selected', self.print_info)
self.fbind('on_press', self.print_info_p)

def print_info(self,*args):
print "on_is_selected: item {}, is_selected: {}, index: {}".format(self, self.is_selected, self.index)
def print_info_p(self,*args):
print "on_press: item {}, is_selected: {}, index: {}".format(self, self.is_selected, self.index)

class MasterDetailView(GridLayout):
def __init__(self, items, **kwargs):
kwargs['cols'] = 2
super(MasterDetailView, self).__init__(**kwargs)

list_item_args_converter = \
lambda row_index, rec: {'text': rec['name'],
'size_hint_y': None,
'height': 25}

dict_adapter = DictAdapter(sorted_keys=sorted(fruit_data.keys()),
data=fruit_data,
args_converter=list_item_args_converter,
selection_mode='single',
allow_empty_selection=False,
propagate_selection_to_data = False,
cls=ClientListItemButton)

master_list_view = ListView(adapter=dict_adapter,
size_hint=(.3, 1.0))

self.add_widget(master_list_view)

detail_view = Label(text=dict_adapter.selection[0].text, size_hint=(.7, 1.0))
dict_adapter.bind(on_selection_change=lambda sel:detail_view.setter('text')(master_list_view, sel.selection[0].text))
self.add_widget(detail_view)
if __name__ == '__main__':
from kivy.base import runTouchApp
master_detail = MasterDetailView(sorted(fruit_data.keys()), width=800)
runTouchApp(master_detail)


Thanks
Jonas
signature.asc

ZenCODE

unread,
Feb 7, 2016, 1:00:55 AM2/7/16
to Kivy users support
Try

    self.fbind('is_selected', self.print_info)

The automatic event in the subclass is 'on_is_selected', but you just use the property name directly for binding...

Jonas Zimmermann

unread,
Feb 7, 2016, 1:41:58 AM2/7/16
to kivy-...@googlegroups.com
D’oh.

Thanks.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

signature.asc
Reply all
Reply to author
Forward
0 new messages