我正在尝试添加一组按钮到使用for循环的网格布局滚动视图。但是,在按下按钮之前,所有按钮都会触发on press事件。我该如何解决这个问题?
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.app import runTouchApp
import webbrowser
def btnsclicked(id, url):
print 'btn id '+id+' clicked'
webbrowser.open(url)
layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
layout.bind(minimum_height=layout.setter('height'))
for i in range(5):
url= 'https://www.google.com'
btn = Button(text=str(i), size_hint_y=None, height=40, id='b'+str(i))
btn.bind(on_press =btnsclicked('b'+str(i), url))
layout.add_widget(btn)
root = ScrollView(size_hint=(1, None), size=(Window.width, Window.height))
root.add_widget(layout)
runTouchApp(root)
对于on_press
,您调用函数而不是指定要使用的函数。试一试:
btn.bind(on_press=lambda x: btnsclicked('b' + str(i), url))
如果您想处理参数,请参见事件调度程序:
def btnsclicked(*args):
id_, url = args
print('btn id {} clicked'.format(id_))
webbrowser.open(url)
btn.bind(on_press=btnsclicked)
因为你在传递参数时实际上是在调用你的回调:
btn.bind(on_press =btnsclicked('b'+str(i), url))
文档示例说:
def callback(instance):
print('The button <%s> is being pressed' % instance.text)
btn1 = Button(text='Hello world 1')
btn1.bind(on_press=callback)
你必须传递一个函数(不是函数调用),只接受一个参数:激活的小部件的实例。
使用定义内联函数的lambda
表达式完成此操作:
btn.bind(on_press = lambda x : btnsclicked('b'+str(i), url))
当一个事件被触发时,on_press
回调调用一个参数:小部件id。这将调用您的lambda
函数,该函数调用btnsclicked
丢弃此参数(您不需要在这里),但传递您的文本id和您想要关联的url。