Python 如何引用一个似乎超出范围的小部件-适应kivy/examples/demo/images

Python 如何引用一个似乎超出范围的小部件-适应kivy/examples/demo/images,python,class,reference,kivy,Python,Class,Reference,Kivy,我编辑了kivy/examples/demo/images文件,尝试执行以下操作: -对于每个添加的图像,它还将在不同的boxlayout侧栏中添加一个按钮 -单击按钮时,会同时删除图像和按钮 为了做到这一点,我创建了这是简短的摘要代码,让您有一个想法 boxlayout: floatlayout: #this is where the images, in their own class called "Picture" just like in the demo get ad

我编辑了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都有自己的根,所以我无法访问它们

我的完整代码如下:

    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/示例中创建了相同的问题,以使其更容易解决


谢谢

好的,我终于找到了一种方法,但我确信一定有更好的方法:

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列表中,但会出现在子项列表中。我仍然不知道这是为什么。如果有人知道更好/更合适的方法,请告诉我。

ID仅在kv中有效,并且与根规则相关。它们不是引用小部件的应用程序范围的全局标识符。下面是一个简单的例子,说明为什么会这样:

<MyWidget@BoxLayout>:
    Label:
        id: mylabel
    Button:
        id: mybutton

BoxLayout:
    MyWidget:
        id: widget1
    MyWidget:
        id: widget2
您的删除代码如下:

def remove_picture(self, idee):
    picture, button = self._pictures.pop(idee)
    picture.parent.remove_widget(picture)
    button.parent.remove_widget(button)

昨天我在Kivy也遇到了scope的问题,并解决了它。你可以看到我的问题和答案。它涉及屏幕,所以它与您的情况并不完全相同,但它仍然可能对您有所帮助。
def remove_picture(self, idee):
    picture, button = self._pictures.pop(idee)
    picture.parent.remove_widget(picture)
    button.parent.remove_widget(button)