如何引用似乎超出范围的小部件 - 改编的 kivy/examples/demo/images

Posted

技术标签:

【中文标题】如何引用似乎超出范围的小部件 - 改编的 kivy/examples/demo/images【英文标题】:How to reference a widgets that seems out of scope - adapted kivy/examples/demo/images 【发布时间】:2014-12-10 00:53:22 【问题描述】:

我已编辑 kivy/examples/demo/images 文件以尝试执行以下操作: - 对于每个添加的图像,它还在侧边栏中添加一个按钮(不同的框布局) - 单击按钮时,它会同时删除图像和按钮

为了做到这一点,我创建了(这是给你一个想法的简短摘要代码)

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 似乎不在任何地方。

我理解它的方式是因为它们超出了范围。 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/examples 中创建了相同的问题,试图使其更容易解决。)

谢谢

【问题讨论】:

我昨天在 Kivy 中也遇到了范围问题并解决了。你可以看到我的问题和答案。它涉及屏幕,因此它与您的情况不完全一样,但它仍然可能对您有所帮助。 ***.com/questions/26366920/… 【参考方案1】:

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

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

BoxLayout:
    MyWidget:
        id: widget1
    MyWidget:
        id: widget2

在这个例子中,id mylabel 指的是哪个小部件? widget1中的实例还是widget2中的实例?

因此,您可以循环遍历子项以查找和删除小部件,也可以自己将引用存储在 dict 中。比如在PicturesApp类上创建一个_pictures 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)

【讨论】:

【参考方案2】:

好吧,我终于找到了办法,但我很确定一定有更好的办法:

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

【讨论】:

以上是关于如何引用似乎超出范围的小部件 - 改编的 kivy/examples/demo/images的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用 Kivy 中的小部件?

Kivy 如何访问子小部件中的小部件

如何删除 kivy 中的小部件?

如何清除 kivy 中的小部件?

Kivy - 使用 .kv

如果未动态添加,如何正确删除Kivy中的小部件