I need to have a ScrollView with a GridLayout inside of it, and then add a varying number of labels to it. I was able to build this with the code below, and the Kivy scroll works beautifully.
But I also need the ScrollView to automatically scroll to any label in the grid. For instance, if the user selects a certain label somewhere else in the application, the ScrollView should automatically scroll to the corresponding label.
I've tried several methods to do this, including changing scroll_y
and using scroll_to()
as in the documentation, but changing scroll_y
does not update the ScrollView until the user manually scrolls with cursor over the ScrollView, and the scroll_to()
method does not scroll at all for me (see code below). Even just auto-scrolling a certain percentage of the ScrollView would work for me.
Does anyone have any suggestions on dealing with this issue? I looked at a lot of similar questions, but couldn't find an answer. I really appreciate any help.
Here is my python code:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Rectangle
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.scrollview import ScrollView
class LabelScroll(ScrollView):
def scroll_to_label(self):
label = LabelGrid.labels_list[75]
self.scroll_to(self, label)
class LabelGrid(GridLayout):
number = 0
labels_list = [] # list to hold labels
def add_label(self):
# this function creates a label and adds to the ScrollView 100 times
if self.number < 100:
label_text = 'text' + str(self.number) # creates unique text
lbl = Label(text=label_text) # adds text to label
self.labels_list.append(lbl) # adds label to list for reference later
self.add_widget(lbl)
self.number = self.number + 1
self.add_label() # code to start this function again
class Frame(FloatLayout):
pass
class ScrollApp(App):
def build(self):
return Frame()
if __name__ == "__main__":
ScrollApp().run()
And here is my kv language file:
#: kivy 2.2.0
<Frame>
Widget:
# this widget is just a canvas to show where
# the ScrollView is located
canvas:
Color:
rgba: (0, .5, .5, 1)
Rectangle:
size: (root.width * .2, root.height)
pos: (root.width * .8, 0)
Button:
# this button triggers the function
# to add the labels to the ScrollView
pos_hint: {'x': .3, 'y': .6}
size_hint: (.2, .2)
text: 'Add labels to ScrollView'
on_press: lbl_grd.add_label()
Button:
# this button triggers the function
# to scroll to label 75
pos_hint: {'x': .3, 'y': .2}
size_hint: (.2, .2)
text: 'Scroll to label 75\n(Hit the other button first)'
on_press: scrlvw.scroll_to_label()
LabelScroll:
# this is the ScrollView
id: scrlvw
pos_hint: {'x': .8}
size_hint_x: .2
do_scroll_x: False
do_scroll_y: True
bar_width: root.width * .007
effect_cls: 'ScrollEffect'
scroll_type: ['bars', 'content']
LabelGrid:
id: lbl_grd
size_hint_y: None
cols: 1
height: self.minimum_height
row_default_height: root.height * .05
Just a minor issue. You don't need a self
argument to an instance method. Try changing:
self.scroll_to(self, label)
to:
self.scroll_to(label)
in your scroll_to_label()
method.