Reputation: 11
I am looking to create buttons in a for loop. my problem is on the on_press property. I read stuff about closures (if that's the problem). But I did not really understand.
a little help.thx sorry for english.
the .py code:
import kivy
import webbrowser
from kivy.app import App
from kivy.uix.button import Label, Button
from kivy.uix.boxlayout import BoxLayout
word_list = ['one', 'two', 'three', 'four']
class LoopButton(BoxLayout):
def aff(self):
for w in word_list:
url = 'https://fr.wiktionary.org/wiki/' + w
button = Button(text= w, on_press= webbrowser.open(url))
self.ids.grid.add_widget(button)
class TestApp(App):
def build(self):
return LoopButton()
if __name__ == '__main__':
TestApp().run()
and the .kv
#:kivy 1.10
<LoopButton>
Label:
text: 'TEST'
Button:
id: 'affiche'
text: 'afficher'
on_press: root.aff()
GridLayout:
id: grid
cols: 2
Upvotes: 0
Views: 2660
Reputation: 16011
on_press=webbrowser.open(url)
will open the webbrowser when instantiating/creating Button widget.
Create a on_press
callback method and create the url in the callback method
class LoopButton(BoxLayout):
def aff(self):
for w in word_list:
button = Button(text=w, on_press=self.open_webbrowser)
self.ids.grid.add_widget(button)
def open_webbrowser(self, instance):
url = 'https://fr.wiktionary.org/wiki/' + instance.text
webbrowser.open(url)
In general, property callbacks are called with 2 arguments (the object and the property’s new value) and event callbacks with one argument (the object).
Upvotes: 1
Reputation: 243897
on_press wants you to pass a callback, and you are passing the evaluated function to it, so there are 3 possible solutions.
Use functools.partial
:
import kivy
import webbrowser
from functools import partial
...
class LoopButton(BoxLayout):
def aff(self):
for w in word_list:
url = 'https://fr.wiktionary.org/wiki/' + w
button = Button(text= w, on_press=partial(webbrowser.open, url))
...
Use lambda
:
button = Button(text= w, on_press= lambda *args, url=url: webbrowser.open(url))
Create a callback:
class LoopButton(BoxLayout):
def aff(self):
for w in word_list:
button = Button(text= w, on_press=self.callback)
self.ids.grid.add_widget(button)
def callback(self, instance):
url = 'https://fr.wiktionary.org/wiki/' + instance.text
webbrowser.open(url)
Upvotes: 1