I am coding a system in kivy that requires the user to input a 3 letter abbreviation of a sports team's name. E.G 'ENG' for England like you would see on a scoreboard. I am trying to use dropdown menus to do this, and am writing these dropdowns in my .kv file. However, at the moment I am having to write them by defining each button in the dropdown individually - 26 different buttons, 3 times over. I know that I can use for loops in kv lang to alter labels or return values, but I cannot find a way to use them to add buttons - what I want to do. Does anyone know of an elegant way to solve my problem?
Here is the .kv code:
<NameScreen>:
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: drop_letters1_menu
text: 'Select Letter'
size_hint_y: None
height: 44
on_parent: drop_player_numbers_tens.dismiss()
on_release: drop_player_numbers_tens.open(self)
DropDown:
id: drop_letters1
on_select:
letter_btn1.text = '{}'.format(args[1])
max_height: 120
Button:
id: btn_a1
text: 'A'
size_hint_y: None
height: 35
on_release: drop_player_numbers_tens.select('1')
Button:
id: btn_b1
text: 'B'
size_hint_y: None
height: 35
on_release: drop_player_numbers_tens.select('self.text')
Button:
id: btn_c1
text: 'C'
size_hint_y: None
height: 35
on_release: drop_player_numbers_tens.select('self.text')
# This continues for all alphabet A-Z
and the .py code:
class NamingScreen(Screen):
pass
class TheApp(App):
alphabet_list = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
# The above line was to try and iterate through an alphabet list for this problem,
# but I got stuck on the main question's issue
def build(self):
# Create the screen manager
sm = ScreenManager()
sm.add_widget(NamingScreen(name='name_screen'))
return sm
def main():
Builder.load_file('menu.kv')
app = TheApp()
app.run()
if __name__ == '__main__':
main()
Any help would be greatly appreciated, and let me know if there is any additional information you need :)
CodePudding user response:
You can either use a default method (like on_start
) or a custom method (in which case you have to call it properly) as follows:
def build(self):
# Create the screen manager
sm = ScreenManager()
sm.add_widget(NamingScreen(name='name_screen'))
return sm
def on_start(self):
# First access the desired screen.
name_screen = self.root.get_screen('name_screen')
# Then access the target drop-down by id.
drop_down = name_screen.ids.drop_player_numbers_tens
# Now iterate over...
for name in self.alphabet_list:
btn = Button(
text = name,
size_hint_y = None,
height = 35,
)
btn.bind(on_release = lambda btn_obj : drop_down.select(btn_obj.text))
drop_down.add_widget(btn)
For that your modified .kv
code will be like,
...
DropDown:
# id: drop_letters1 # Not consistent !
id: drop_player_numbers_tens
on_select:
drop_letters1_menu.text = '{}'.format(args[1])
# letter_btn1.text = '{}'.format(args[1])
max_height: 120
# Button:
# id: btn_a1
# text: 'A'
# size_hint_y: None
# height: 35
# on_release: drop_player_numbers_tens.select('1')
...