我编辑了kivy / examples / demo / images文件以尝试执行以下操作: - 对于每个添加的图像,它还在侧栏中添加一个按钮(不同的boxlayout) - 单击按钮时,它会删除图像和按钮
为了做到这一点,我创建了(这是一个简短的摘要代码,可以给你一个想法)
boxlayout:
floatlayout:
#this is where the images, in their own class called "Picture" just like in the demo get added
boxlayout:
#this is where the buttons get added. I created a class for them called "PictureBtn"
创建图片时,我会为其添加唯一ID。 然后我创建PictureBtn并添加相同的ID。 然后我在各自的位置填充图片和按钮。一切都很好。
现在的问题是,从Pictures和PictureBtn实例,我可以引用应用程序,但我不知道如何引用其他实例。身份证似乎不在任何地方。
我理解它的方式是因为它们超出了范围。 id只能在本地保存,因为PictureBtn和Pictures都有自己的root,我无法找到它们。
我的完整代码如下:
import kivy
kivy.require('1.0.6')
from glob import glob
from random import randint
from os.path import join, dirname
from kivy.app import App
from kivy.logger import Logger
from kivy.uix.scatter import Scatter
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
# FIXME this shouldn't be necessary
from kivy.core.window import Window
#declare global var for keeping track of unique ids
number_of_pics=0
class Picture(Scatter):
'''Picture is the class that will show the image with a white border and a
shadow. They are nothing here because almost everything is inside the
picture.kv. Check the rule named <Picture> inside the file, and you'll see
how the Picture() is really constructed and used.
The source property will be the filename to show.
'''
source = StringProperty(None)
class PictureBtn(BoxLayout):
pass
class PicturesApp(App):
def build(self):
global number_of_pics
# the root is created in pictures.kv
root = self.root
# get any files into images directory
curdir = dirname(__file__)
for filename in glob(join(curdir, 'images', '*')):
try:
# load the image
picture = Picture(source=filename, rotation=randint(-30,30))
picture.id='pic'+str(number_of_pics)
button = PictureBtn()
button.id = 'pic'+str(number_of_pics)
button.ids.lbl.text= button.id
# add to the main field
self.root.ids.picspace.add_widget(picture)
self.root.ids.sidebar.add_widget(button)
number_of_pics+=1
except Exception as e:
Logger.exception('Pictures: Unable to load <%s>' % filename)
def on_pause(self):
return True
def RemovePicture(self,byid):
#my attempt (obviously failing) at removing the Picture instance and the
#PictureBtn instance with the id "byid"
self.root.ids.sidebar.remove_widget(self.root.ids.sidebar.ids.byid)
self.root.ids.picspace.remove_widget(self.root.ids.picspace.ids.byid)
if __name__ == '__main__':
PicturesApp().run()
然后我的kv文件包含以下内容:
#:kivy 1.0
#:import kivy kivy
#:import win kivy.core.window
BoxLayout:
orientation: 'horizontal'
FloatLayout:
id: picspace
size_hint: 0.8,1
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
source: 'data/images/background.jpg'
size: self.size
BoxLayout:
padding: 10
spacing: 10
size_hint: 1, None
pos_hint: {'top': 1}
height: 44
Image:
size_hint: None, None
size: 24, 24
source: 'data/logo/kivy-icon-24.png'
Label:
height: 24
text_size: self.width, None
color: (1, 1, 1, .8)
text: 'Kivy %s - Pictures' % kivy.__version__
BoxLayout:
id: sidebar
orientation: 'vertical'
<Picture>:
# each time a picture is created, the image can delay the loading
# as soon as the image is loaded, ensure that the center is changed
# to the center of the screen.
on_size: self.center = win.Window.center
size: image.size
size_hint: None, None
Image:
id: image
source: root.source
# create initial image to be 400 pixels width
size: 400, 400 / self.image_ratio
# add shadow background
canvas.before:
Color:
rgba: 1,1,1,1
BorderImage:
source: 'shadow32.png'
border: (36,36,36,36)
size:(self.width+72, self.height+72)
pos: (-36,-36)
<PictureBtn>:
orientation: 'horizontal'
Label:
id: lbl
text: ''
Button:
text: 'X'
on_release: app.RemovePicture(self.parent.id)
(我的原始代码是类似的情况,但我在其中一个kivy / examples中创建了同样的问题,试图让它更容易解决。)
由于
答案 0 :(得分:0)
好的,我终于找到了办法,但我确信必须有更好的方法:
def RemovePicture(self,idee):
for child in self.ids.picspace.children:
if child.id==idee:
self.ids.picspace.remove_widget(child)
for child in self.ids.sidebar.children:
if child.id==idee:
self.ids.sidebar.remove_widget(child)
所以这似乎有效。它们不会显示在ID列表中,但它们会显示在子列表中。我仍然不确定为什么会这样。如果有人知道更好/更合适的方式,请告诉我。
答案 1 :(得分:0)
id
仅在kv中有效,并且与根规则相关。它们不是应用程序范围的全局标识符,用于引用您的小部件。以下是一个简单的例子:
<MyWidget@BoxLayout>:
Label:
id: mylabel
Button:
id: mybutton
BoxLayout:
MyWidget:
id: widget1
MyWidget:
id: widget2
在此示例中,id mylabel
引用哪个小部件? widget1
中的实例或widget2
中的实例?
因此,您可以遍历子项以查找和删除小部件,也可以将自己的引用存储在dict中。例如,在_pictures
类上创建PicturesApp
dict,然后在添加图片时:
# add to the main field
self._pictures[number_of_pics] = (picture, button)
self.root.ids.picspace.add_widget(picture)
self.root.ids.sidebar.add_widget(button)
您的删除代码将变为:
def remove_picture(self, idee):
picture, button = self._pictures.pop(idee)
picture.parent.remove_widget(picture)
button.parent.remove_widget(button)