在按下按钮之前调用按下按钮

button on press being called before button press

我正在尝试使用 for 循环将一组按钮添加到网格布局滚动视图。但是即使在按下按钮之前,所有按钮的按下事件也会被触发。我该如何解决这个问题?

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)

因为您在传递参数时实际上是在调用回调:

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)

您必须传递一个仅接受 1 个参数的函数(不是函数调用):激活的小部件的实例。

使用 lambda 内联定义函数的表达式执行此操作:

btn.bind(on_press = lambda x : btnsclicked('b'+str(i), url))

当一个事件被触发时,on_press 回调被调用并带有一个参数:widget id。这会调用您的 lambda 函数,该函数会调用 btnsclicked 丢弃此参数(此处不需要),但会传递您的文本 ID 和要关联的 url。

对于on_press,您调用函数而不是指定要使用的函数。尝试:

btn.bind(on_press=lambda x: btnsclicked('b' + str(i), url))

如果要处理参数,请参阅 Event dispatcher:

def btnsclicked(*args):
    id_, url = args
    print('btn id {} clicked'.format(id_))
    webbrowser.open(url)

btn.bind(on_press=btnsclicked)