【问题标题】:Multiple Kivy DropDown Lists Strange Bug多个 Kivy 下拉列表奇怪的错误
【发布时间】:2021-08-30 12:26:40
【问题描述】:

我遇到了一个带有多个 Kivy DropDown 小部件的奇怪错误。构建了以下 GUI 原型,其中所有 10 个 DropDown 小部件都是通过相同的方法生成的:

但其中只有 6 个有效。其他 4 个下拉菜单:“Cars”、“Green”、“Westie”、“Chicken”在单击时不显示任何内容。

我的源代码如下:

from typing import List, OrderedDict
from functools import partial
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.widget import Widget

_category_list = ["Food", "Colors", "Dogs", "Cars", "Fruits"]
_food_list = ["Chicken", "Fish"]
_cars_list = [
    "Acura",
    "Audi",
    "BMW",
    "Hyundai",
    "Mercedes",
    "Nissan",
    "Toyota",
    "Volvo",
]
_colors_list = ["Red", "Green", "Blue", "Yellow"]
_dogs_list = [
    "Bulldog",
    "Chihuahua",
    "Dobermann",
    "Husky",
    "Labrador",
    "Pomeranian",
    "Poodle",
    "Retriever",
    "Westie",
]
_fruits_list = ["Apple", "Orange", "Watermelon"]
_node_to_stuff_map = {
    "Cars": _cars_list,
    "Colors": _colors_list,
    "Dogs": _dogs_list,
    "Food": _food_list,
    "Fruits": _fruits_list,
}

class MainScreen(Screen):
    def add_list_node(self, node: Widget):
        self.mylist.add_widget(node)

class Manager(ScreenManager):
    pass

Builder.load_string(
    """
<MainScreen>:
    mylist: id_mylist

    BoxLayout:
        orientation: "vertical"

        BoxLayout:
            orientation: "horizontal"
            size_hint: 1.0, 0.1
            Label:
                text: "Category"
            Label:
                text: "Item List"
            Label:
                text: "Parameters"

        BoxLayout:
            id: id_mylist
            orientation: "vertical"
            size_hint: 1.0, 0.9
"""
)

class DropDownListBug(App):
    def build(self):
        self.main_screen = MainScreen()
        smgr = ScreenManager()
        smgr.add_widget(self.main_screen)
        self.make_my_lists()
        return smgr

    def make_ddl(self, a_node: str, a_node_list) -> DropDown:
        def select(drop_button, text, btn):
            drop_button.text = text

        ddl = DropDown()
        ddl_main = Button(text=a_node, size_hint=(1, None), height=50)
        for node_type in a_node_list:
            btn = Button(text=node_type, size_hint=(1, None), height=50)
            btn.bind(on_release=partial(select, ddl_main, btn.text))
            btn.bind(on_release=ddl.dismiss)
            ddl.add_widget(btn)
        ddl_main.bind(on_press=ddl.open)
        return ddl_main

    def make_my_lists(self):
        my_list = [
            "Cars.Hyundai",
            "Colors.Green",
            "Dogs.Westie",
            "Food.Chicken",
            "Fruits.Apple",
        ]

        for node in my_list:
            toks = node.split(".")
            node_type, node_item = toks[0], toks[1]

            node_panel = BoxLayout(orientation="horizontal")

            dll_category = self.make_ddl(node_type, _category_list)
            node_panel.add_widget(dll_category)

            item_list = _node_to_stuff_map[node_type]
            ddl_items = self.make_ddl(node_item, item_list)
            node_panel.add_widget(ddl_items)

            lbl = Label(text="[params]", size_hint=(1, None), height=50)
            node_panel.add_widget(lbl)

            self.main_screen.add_list_node(node_panel)

if __name__ == "__main__":
    DropDownListBug().run()

更令人困惑的是,如果您更改列表的长度,工作/不工作的 DropDown 小部件会发生变化!

例如从汽车中删除“Toyota”、“Volvo”并添加“White”颜色:不工作的 DropDowns 现在变为“Cars”、“Colors”、“Dogs”、“Chicken”。 太奇怪了。

【问题讨论】:

    标签: python debugging kivy kivy-language


    【解决方案1】:

    问题是 python 正在做垃圾收集,删除未引用的对象。 make_ddl() 方法中的 ddl 变量包含 DropDown 实例,并且一旦 make_ddl() 返回,该变量将变为未引用并有资格进行垃圾收集。结果是,在某些情况下,当按下Button 时,DropDown 不再存在。一个简单的技巧是保持对DropDown 的引用,这样它就不会被垃圾收集。像这样:

        ddl = DropDown()
        ddl_main = Button(text=a_node, size_hint=(1, None), height=50)
        ddl_main.ddl = ddl
    

    现在Button 持有对其DropDown 的引用,因此它不会变为未引用。

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      • 2018-08-30
      • 2012-06-19
      相关资源
      最近更新 更多