I have a recycleview of several thousand songs. I want to force a selection when I shuffle songs. I can force scrolling to the selected song by setting scroll_y
but I cannot seem to get the item in the recycleview to display as selected as with the basic kivy recycleview example where you click on an item and it changes background color.
I have a basic example. If you click it should start the random item selection every 0.5 sec and print out the rv.data showing that the items have 'selected': True.
I've tried setting key_selection: 'selected' and I've also set 'selected': True in the recycleview.data.
MPROSRVbug.kv
<Manachan>:
id: manachanID
SelectionScreen:
id: selectscreenID
name: 'selectscreen'
manager: 'manachanID'
<SelectionScreen>:
id: selectionscreenid
BoxLayout:
orientation: 'horizontal'
Video:
id: previewVideo
SongList:
id: songlistid
<SongList>
cols: 1
size_hint_x: 1
BoxLayout:
size_hint: (1,.1)
orientation: 'vertical'
Label:
id: songtitle
canvas.before:
Color:
rgba: (.3, .3, .3, 1)
Rectangle:
pos: self.pos
size: self.size
RV:
id: recycle_grid1
size_hint_x: 1
<RV>:
viewclass: 'SongLinkButton'
SelectableRecycleBoxLayout:
id: recycle_grid2
default_size: None, dp(120)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<SongLinkButton>:
id: songbutton
orientation: 'horizontal'
height: '80dp'
# 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
Label:
id: textinfo
text_size: self.width, None
MPROSRVbug.py
#MUSIC PLAYER RANDOM ORDERED SORT
import os, sys
from random import *
songDict = {}
songVal = {}
i = 0
for mp3file in ["1","9","7k","r","j","i","7","g","a","2",]:
songDict[i] = mp3file
songVal[str(mp3file)] = 0
i += 1
if i > 7:
break
import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.recycleview import RecycleView
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.views import RecycleKVIDsDataViewBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import *
from kivy.core.audio import SoundLoader
from kivy.uix.scrollview import ScrollView
from kivy.clock import Clock
import traceback
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
#set self.data:
self.data = [{'textinfo.text': x, 'selected': False} for x in [songDict[y] for y in songDict]]
print("self.data item?", self.data[0], len(self.data))
def scroll_to_index(self, index):
box = self.children[0]
pos_index = (box.default_size[1] + box.spacing) * index
scroll = self.convert_distance_to_scroll(
0, pos_index - (self.height * 0.5))[1]
if scroll > 1.0:
scroll = 1.0
elif scroll < 0.0:
scroll = 0.0
self.scroll_y = 1.0 - scroll
def NextSong(self, *args):
rvRef = App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"]
randPickInt = randint(0,len(rvRef.data)-1)
for d in rvRef.data:
if d['textinfo.text'] == songDict[randPickInt]:
d['selected'] = True
dictElement = d
target = os.path.normpath(rvRef.data[randPickInt]['textinfo.text'])
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["songtitle"].text = target
targettextOG = rvRef.data[randPickInt]['textinfo.text']
#PLAN: apply_selection always triggers when reycycleview refreshes, so set a global var of the selected guy. within the widget, if the name is the same as the selected guy, make yourself selected
global curSelectedSong
curSelectedSong = rvRef.data[randPickInt]['textinfo.text']
counter = 0
for d in rvRef.data:
#remove all previously selected
if d['selected']:
d['selected'] = False
#if we found the song, change to selected
if d['textinfo.text'] == targettextOG:
#print("VERSING", d['textinfo.text'], targettextOG, d['textinfo.text'] == targettextOG)
d['selected'] = True
#print("so has d updated?", d)
rvRef.data[counter] = d
print("updated rvRef.data", rvRef.data[counter])
counter += 1
print("WHAT IS RV DATA?", rvRef.data)
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"].scroll_to_index(randPickInt)
rvRef.refresh_from_data()
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
def __init__(self, **kwargs):
super(SelectableRecycleBoxLayout, self).__init__(**kwargs)
def WeightedChoice():
pass
class SongLinkButton(RecycleKVIDsDataViewBehavior,BoxLayout,Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def __init__(self, **kwargs):
super(SongLinkButton, self).__init__(**kwargs)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SongLinkButton, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SongLinkButton, 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):
global curSelectedSong
try:
if curSelectedSong == rv.data[index]["textinfo.text"]:
self.selected == True
except:
pass
global soundObj
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected and App.get_running_app().root.current == 'selectscreen':
target = os.path.normpath(rv.data[index]['textinfo.text'])
Clock.schedule_interval(App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"].NextSong, 1)
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["songtitle"].text = target
else:
pass
class Manachan(ScreenManager):
pass
class SongList(GridLayout):
pass
class SelectionScreen(Screen):
pass
class MyApp(App):
def build(self):
self.load_kv('MPROSRVbug.kv')
self.title = "Music Player Random Ordered Sort by Pengindoramu"
return Manachan()
if __name__ == '__main__':
MyApp().run()