I need to create scrollview functionality in my Kivy App, but without using kv file.
Below my code is not working. I think I am on wrong way. Please help me. I need to create frame in the middle of window and only 2 buttons should be visible and user could be able to scroll the list of buttons cyclically only down.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.scrollview import ScrollView
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
class MyApp(App):
def build(self):
self.create_scrollview()
Window.size = (900, 600)
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.2, 0.6)
self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}
self.some_words = Label(font_size='16', text='Win or Lose', color='white', halign='center')
self.window.add_widget(self.some_words)
self.button_1 = Button(text='1st button', background_color='#04D0F9')
self.button_1.size_hint = (0.2, 0.2)
self.button_1.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_1.bind(on_press=self.ask1)
self.window.add_widget(self.button_1)
self.button_2 = Button(text='2nd button', background_color='#04D0F9')
self.button_2.size_hint = (0.2, 0.2)
self.button_2.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_2.bind(on_press=self.ask2)
self.window.add_widget(self.button_2)
self.button_3 = Button(text='3rd button', background_color='#04D0F9')
self.button_3.size_hint = (0.2, 0.2)
self.button_3.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_3.bind(on_press=self.ask3)
self.window.add_widget(self.button_3)
self.button_4 = Button(text='4th button', background_color='#04D0F9')
self.button_4.size_hint = (0.2, 0.2)
self.button_4.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_4.bind(on_press=self.ask4)
self.window.add_widget(self.button_4)
self.button_5 = Button(text='5th button', background_color='#04D0F9')
self.button_5.size_hint = (0.2, 0.2)
self.button_5.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_5.bind(on_press=self.ask5)
self.window.add_widget(self.button_5)
self.button_6 = Button(text='6th button', background_color='#04D0F9')
self.button_6.size_hint = (0.2, 0.2)
self.button_6.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_6.bind(on_press=self.ask6)
self.window.add_widget(self.button_6)
return self.window
def ask1(self, instance):
self.some_words.text = 'Test 1'
def ask2(self, instance):
self.some_words.text = 'Test 2'
def ask3(self, instance):
self.some_words.text = 'Test 3'
def ask4(self, instance):
self.some_words.text = 'Test 4'
def ask5(self, instance):
self.some_words.text = 'Test 5'
def ask6(self, instance):
self.some_words.text = 'Test 6'
def create_scrollview(self):
base = (self.button_1, self.button_2, self.button_3, self.button_4, self.button_5, self.button_6)
layout = GridLayout(cols=1)
layout.bind(minimum_height=layout.setter("height"))
for element in base:
button = Button(text=str(element), size_hint=(1, 0.1))
layout.add_widget(button)
scrollview = ScrollView(size=(Window.width, Window.height))
scrollview.add_widget(layout)
self.window.add_widget(scrollview)
if __name__ == "__main__":
MyApp().run()
My updated code is below. This code is not working properly as well. No buttons are visible, only the text is visible on black background. Please help. Maybe I did something wrong. App is opened, without error but expected result is buttons scrolling functionality which is no working.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.scrollview import ScrollView
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
class MyApp(App):
def create_scrollview(self):
base = (self.button_1, self.button_2, self.button_3,
self.button_4, self.button_5, self.button_6)
layout = GridLayout(cols=1, size_hint_y=None)
layout.bind(minimum_height=layout.setter("height"))
for element in base:
button = Button(text=str(element), size_hint=(1, None))
layout.add_widget(button)
scrollview = ScrollView(size=(Window.width, Window.height))
scrollview.add_widget(layout)
self.window.add_widget(scrollview)
def build(self):
Window.size = (900, 600)
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.2, 0.6)
self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}
self.some_words = Label(font_size='16', text='Win or Lose',
color='white', halign='center')
self.window.add_widget(self.some_words)
self.button_1 = Button(text='1st button',
background_color='#04D0F9')
self.button_1.size_hint = (0.2, 0.2)
self.button_1.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_1.bind(on_press=self.ask1)
self.button_2 = Button(text='2nd button',
background_color='#04D0F9')
self.button_2.size_hint = (0.2, None)
self.button_2.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_2.bind(on_press=self.ask2)
self.button_3 = Button(text='3rd button',
background_color='#04D0F9')
self.button_3.size_hint = (0.2, None)
self.button_3.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_3.bind(on_press=self.ask3)
self.button_4 = Button(text='4th button',
background_color='#04D0F9')
self.button_4.size_hint = (0.2, None)
self.button_4.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_4.bind(on_press=self.ask4)
self.button_5 = Button(text='5th button',
background_color='#04D0F9')
self.button_5.size_hint = (0.2, None)
self.button_5.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_5.bind(on_press=self.ask5)
self.button_6 = Button(text='6th button',
background_color='#04D0F9')
self.button_6.size_hint = (0.2, None)
self.button_6.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button_6.bind(on_press=self.ask6)
return self.window
def ask1(self, instance):
self.some_words.text = 'Test 1'
def ask2(self, instance):
self.some_words.text = 'Test 2'
def ask3(self, instance):
self.some_words.text = 'Test 3'
def ask4(self, instance):
self.some_words.text = 'Test 4'
def ask5(self, instance):
self.some_words.text = 'Test 5'
def ask6(self, instance):
self.some_words.text = 'Test 6'
if __name__ == "__main__":
MyApp().run()
Update: I have changed code, but there is still incorrect reflection. As you can see from my code I am expected the buttons like "1st button", "2nd button" and etc. But the reflection is not correct. I can't understand how I need to fix it. Also, the button functionality is not working. For example I need to see "Test 1" while clicking to "1st button", but nothing happened when I am clicking to any button.
You're just missing some little things:
You're adding every single button you create to self.window
,then you add the same buttons to the SrollView, so you got duplicated widgets. Delete this line for every button: self.window.add_widget(self.button_6)
When you run your kivy app, first it loads the .kv
file (In this case don't have this), after that, runs the App.build()
method. As any other func in python, build()
is a sync function so the first thing you do is to call self.create_scrollview()
method, which needs all the buttons to work... The problem is that the buttons haven't been created at this point so you'll get an error. The solution is to move self.create_scrollview()
before the return of the function build()
.
In order to be able to scroll, you must deactivate at least one of the size_hint instructions (x or y) of the child to enable scrolling. So all your buttons and the grid layout that contains the buttons must have size_hint=(1,None)
or size_hint_y=None
. So:
def create_scrollview(self):
base = (self.button_1, self.button_2, self.button_3, self.button_4, self.button_5, self.button_6)
layout = GridLayout(cols=1, size_hint_y=None)
layout.bind(minimum_height=layout.setter("height"))
for element in base:
button = Button(text=str(element), size_hint=(1, None))
layout.add_widget(button)
scrollview = ScrollView(size=(Window.width, Window.height))
scrollview.add_widget(layout)
self.window.add_widget(scrollview)
As you can see I just modified some liitle things but that will fix your code
Create a custom class for your button so you everybutton have the callback you want:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.scrollview import ScrollView
from kivy.properties import NumericProperty
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
class MyButton(Button):
num = NumericProperty(0)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size_hint = (0.2, None)
self.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.background_color = '#04D0F9'
def on_press(self):
App.get_running_app().some_words.text = f'Test {self.num}'
class MyApp(App):
def build(self):
Window.size = (900, 600)
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.2, 0.6)
self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}
self.some_words = Label(font_size='16', text='Win or Lose', color='white', halign='center')
self.window.add_widget(self.some_words)
self.create_scrollview()
return self.window
def create_scrollview(self):
listNames = ['1st Button', '2nd button', '3rd button', '4th button', '5th button', '6th button']
layout = GridLayout(cols=1, size_hint_y=None)
layout.bind(minimum_height=layout.setter("height"))
for i in range(6):
button = MyButton(text=listNames[i], num=i+1)
layout.add_widget(button)
layout.ids[str(i+1)]=button
scrollview = ScrollView(size=(Window.width, Window.height))
scrollview.add_widget(layout)
self.window.add_widget(scrollview)
if __name__ == "__main__":
MyApp().run()