如何解决如何从文件Python Kivy APP中的变量项创建功能按钮
我实际上是在尝试创建应用程序,但是遇到了一个大问题
具体来说,它应该检查一个装有图片的文件夹以查找其项目,并应为每个项目在Scollview GridLayout列表中创建一个ImageButton(已定义)。到目前为止,它仍然有效。
但是当按下显示的图片之一时,我希望它改变主屏幕上图片的路径
这是我的Python代码
#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
这是路径文件夹包含的内容:
... cars \ 01_test_golf8_tez.jpg
... cars \ 02_test_golf7_tez.jpg
... cars \ 03_test_passat_te.jpg
... cars \ 04_test_crafter_t.jpg
所有照片都放置正确。对于绑定后打印的每个“ z”,它都会在内存中显示一个不同的对象,因此直到此处一切都很好为止
但这是我的问题所在。
假设您要选择帕萨特,然后按一下它的图片,但是无论如何,无论您按什么图片,选择功能都将始终打印“ ... cars \ 04_test_crafter_t.jpg”
如何将1个按钮绑定到其功能上?
这是找到的最接近的答案,但是我不理解如何在我的代码中使用和集成它,或者它根本无济于事[lambda x,i = i:i * x for i in range(len(图片))],因为它不起作用
解决方法
这可能不是完整的答案,但是我不能在注释中挤很多代码。
列出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]
,然后将每张图片附加到列表中:
chosen
关于“黑客”
目标函数(lamda)不会立即运行。定义函数时,python使用 late绑定。这样,python将存储方法地址(lambda)和参数地址(i)。它不会不存储参数的值。以后调用该函数时,将使用参数变量的当前(最新)值。
以这个例子为例。调用i
时,i
等于2,因为这是循环完成后但实际调用函数之前的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
该黑客通过强制早期绑定解决了此问题。使用def myfunc(i=5)
告诉python该参数有一个默认值(如for i in range(3): 0-2
tmp.bind(on_release=lambda x,i=i:self.chosen(i)) # value of i is stored
),应使用早期绑定。使用早期绑定,创建方法时将存储(默认)参数值,从而解决了循环问题。
x
可能不需要{{1}}参数。您可以尝试进行确认。
@inclement在他的评论中提供了一个有用的链接:https://docs.python-guide.org/writing/gotchas/#late-binding-closures
,我认为问题出在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
您可以使用on_touch_down函数的touch
参数进行检查。检查touch.pos
与哪个按钮碰撞器碰撞。即使仅按下一个按钮,on_touch_down
事件也会触发所有ImageButton!
我总是使用Button id来标识按钮-并将其与更多数据链接。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。