如何从文件Python Kivy应用程序中的变量项创建函数按钮
我实际上正在尝试创建一个应用程序,但遇到了一个大问题 具体来说,它应该检查一个包含图片的文件夹中的项目,并为每个项目在Scollview GridLayout列表中创建一个ImageButton(已定义)。到目前为止还有效 但当按下其中一张显示的图片时,我希望它改变主屏幕上图片的路径 这是我的Python代码如何从文件Python Kivy应用程序中的变量项创建函数按钮,python,python-3.x,kivy,kivy-language,kivymd,Python,Python 3.x,Kivy,Kivy Language,Kivymd,我实际上正在尝试创建一个应用程序,但遇到了一个大问题 具体来说,它应该检查一个包含图片的文件夹中的项目,并为每个项目在Scollview GridLayout列表中创建一个ImageButton(已定义)。到目前为止还有效 但当按下其中一张显示的图片时,我希望它改变主屏幕上图片的路径 这是我的Python代码 #This is outside the MDApp class class ImageButton(ButtonBehavior, Image): #Inside the MDApp
#This is outside the MDApp class
class ImageButton(ButtonBehavior, Image):
#Inside the MDApp class
def item_choser(self, item)
.
.
.
elif item == "car":
#It first clears the grid layout
self.root.ids.pictures_grid.clear_widgets()
#Then, the path folder of the items(pictures) is being defined
pictures = glob.glob(f"./images/items/cars/*.jpg")
#For loop created to assign
for i in pictures:
#This "z" is the number after path in format <path\02_test_golf7_tez.jpg>
#Different for every picture (01, 02, 03 etc)
z = i[-21:-19]
#Creating button with bind
z = ImageButton(source=i, allow_stretch=True, keep_ratio=True)
z.bind(on_release=lambda x:self.chosen(i)) <<--- Here is my actual problem
print(z)
#Adding it into the grid
self.root.ids.pictures_grid.add_widget(z)
def chosen(self, selectedCar):
print(selectedCar)
self.root.ids.main_image_display.source = selectedCar
#这不属于MDApp类
类ImageButton(按钮行为,图像):
#在MDApp类中
def项目(自身、项目)
.
.
.
elif项目==“汽车”:
#它首先清除网格布局
self.root.ids.pictures\u grid.clear\u widgets()
#然后,定义项目(图片)的路径文件夹
图片=glob.glob(f.“/images/items/cars/*.jpg”)
#用于创建要分配的循环
对于图片中的我:
#此“z”是格式中路径后的数字
#每幅图片都不同(01、02、03等)
z=i[-21:-19]
#使用绑定创建按钮
z=ImageButton(源=i,允许拉伸=True,保持比率=True)
z、 bind(on_release=lambda x:self.selected(i))这可能不是完整的答案,但我无法在注释中压缩太多代码
制作gala
列表,然后将每张图片附加到列表中:
gala = []
for i in pictures:
z = i[-21:-19]
tmp = ImageButton(source=i, allow_stretch=True, keep_ratio=True)
tmp.bind(on_release=lambda x, i=i:self.chosen(i)) # closure hack
self.root.ids.pictures_grid.add_widget(tmp)
gala.append(tmp) # can reference later > gala[0]
关于“黑客”
目标函数(lamda)不会立即运行。定义函数时,python使用后期绑定。这样,python存储方法地址(lambda)和参数地址(i)。它不存储参数的值。稍后调用该函数时,将使用参数变量的当前(最新)值
就拿这个例子来说。调用selected
时,i
将等于2,因为这是循环完成但实际调用函数之前i
的值
for i in range(3): 0-2
tmp.bind(on_release=lambda i:self.chosen(i)) # address of i is stored, not value
黑客通过强制早期绑定来解决这个问题。使用i=i
告诉python该参数有一个默认值(如def myfunc(i=5)
),应该使用早期绑定。使用早期绑定,在创建方法时存储(默认)参数值,从而解决循环问题
for i in range(3): 0-2
tmp.bind(on_release=lambda x, i=i:self.chosen(i)) # value of i is stored
可能不需要x
参数。你可以通过实验来确认
@恶劣天气在他的评论中提供了一个有用的链接:我假设问题出在ImageButton类中-您需要在那里检查按钮是否被按下
class ImageButton(Button):
# ....
def on_touch_down(self, touch):
"""
Check which of the buttons was pressed
:param touch:
:return:
"""
if self.collide_point(*touch.pos):
print(self.source)
# You could then trigger an event from here and pass the Source/ID whatever as parameter
else:
# This Button wasn't pressed
pass
您可以使用该功能的touch
参数进行检查。检查touch.pos
与哪个按钮碰撞。即使只按下一个按钮,所有图像按钮都会触发on\u touch\u down
事件
我总是使用按钮id来标识按钮,并将其与更多数据链接。在循环中创建函数时遇到了一个常见问题,请参阅。此语法导致错误:gala+z=…
。gala
应该是一个集合吗?@Mike67-不,它们应该是变量,我想在其末尾添加不同的数字,这样它们就可以不同,以便绑定正常工作。@谢谢您的反馈。你发送的URL实际上有帮助,但我不明白它是如何工作的,所以我无法在代码中实现它(你可以在我的主要问题的最后一行中看到)…你好,有趣的想法,但我认为它在我的情况下不起作用,因为我的ImageButton类不是应用程序的一部分,所以它不知道self function Plus,我的按钮的继承有点不同:类ImageButton(ButtonBehavior,Image):起初我不理解您所说的,但现在它有了意义。尽管如此,在创建列表后,我打印了它,实际上它在内存中显示了4个不同的项目。但当按下第一张图片时,它仍然显示“所选”功能中的最后一个。我仍在试图理解“黑客”是如何工作的,因为对我来说,这毫无意义。。。但那东西行得通!非常感谢你的帮助!非常感谢你,迈克!确切地说,我试图理解@increment中的示例,但我不确定如何在代码中实现它,因为它没有意义。