无法从Kivy的DropDown小部件中获得正确的项目选择

问题描述 投票:0回答:1

在我的Kivy应用中,当on_focus时,文本输入之一触发DropDown小部件的打开。文本输入是自定义BoxLayout IngredientRow的一部分,我只需按一下按钮就可以将其输入到屏幕上。

我想要的是用从DropDown中选择的按钮的文本填充textinput。这适用于第一个IngredientRow。但是,当我添加新行时,从DropDown中选择与第一行不同的行中的一项,将填充第一行中的textinput。参见下面的一个最小的工作示例:

py文件:

from kivy.app import App
from kivy.factory import Factory
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput


class DelIngButton(Button):
    pass
class DropListButton(Button):
    def __init__(self, **kwargs):
        super(DropListButton, self).__init__(**kwargs)
        self.bind(on_release=lambda x: self.parent.parent.select(self.text))
class IngredientRow(BoxLayout):
    pass
class MeasureDropDown(DropDown):
    pass

####################################
class AddWindow(Screen):
    def __init__(self, **kwargs):
        super(AddWindow, self).__init__(**kwargs)

        self.DropDown = MeasureDropDown()

    def addIngredient(self, instance): #adds a new IngredientRow
        row = instance.parent
        row.remove_widget(row.children[0])
        row.add_widget(Factory.DelIngButton(), index=0)
        self.ingsGrid.add_widget(Factory.IngredientRow(), index=0)


class WMan(ScreenManager):
    def __init__(self, **kwargs):
        super(WMan, self).__init__(**kwargs)

kv = Builder.load_file("ui/layout.kv")

class RecipApp(App):
    def build(self):
        return kv

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

和kv文件:

#:set text_color 0,0,0,.8

#:set row_height '35sp'

#:set main_padding ['10sp', '10sp']
#:set small_padding ['5sp', '5sp']


<DropListButton>: # Button for custom DropDown
    color: text_color
    background_normal: ''

<DelIngButton>: # Button to delete row
    text: '-'
    size_hint: None, None
    height: row_height
    width: row_height
    on_release: self.parent.parent.remove_widget(self.parent)

<MeasureDropDown>:
    id: dropDown
    DropListButton:
        size_hint: 1, None
        height: row_height
        text: "g"
    DropListButton:
        size_hint: 1, None
        height: row_height
        text: "Kg"
    TextInput:
        size_hint: 1, None
        height: row_height
        hint_text: 'new'

<IngredientRow>:
    orientation: 'horizontal'
    size_hint: 1, None
    height: row_height
    spacing: '5sp'
    TextInput:
        id: ing
        hint_text: 'Ingredient'
        multiline: False
        size_hint: .6, None
        height: row_height
    TextInput:
        id: quant
        hint_text: 'Quantity'
        multiline: False
        size_hint: .2, None
        height: row_height
    TextInput:
        id: measure
        hint_text: 'measure'
        size_hint: .2, None
        height: row_height
        on_focus:
            app.root.ids.add.DropDown.open(self) if self.focus else app.root.ids.add.DropDown.dismiss(self)
            app.root.ids.add.DropDown.bind(on_select=lambda self, x: setattr(app.root.ids.add.ingredientRow.children[1], 'text', x))
    Button:
        id: addIng
        text: "+"
        size_hint: None, None
        height: row_height
        width: row_height
        on_release: app.root.ids.add.addIngredient(self)


<MainScrollView@ScrollView>:
    size_hint: 1, None
    scroll_type: ['bars', 'content']

##################
# Windows
##################

WMan:
    AddWindow:
        id: add

<AddWindow>:
    name: 'add'
    ingsGrid: ingsGrid
    ingredientRow: ingredientRow

    MainScrollView:
        height: self.parent.size[1]
        GridLayout:
            cols:1
            size_hint: 1, None
            pos_hint: {"top": 1}
            height: self.minimum_height
            padding: main_padding
            StackLayout:
                id: ingsGrid
                size_hint: 1, None
                height: self.minimum_height
                orientation: 'lr-tb'
                padding: small_padding
                IngredientRow:
                    id: ingredientRow

我了解问题出在代码的以下部分:

on_select=lambda self, x: setattr(app.root.ids.add.ingredientRow.children[1], 'text', x)

因为这将始终称为第一个成分行。但是,我不知道如何引用调用DropDown的IngredientRow。

python kivy dropdown
1个回答
0
投票

问题是,每次measure TextInput获得焦点时,都会将另一个lambda函数添加到on_selectMeasureDropDown事件中,并且没有绑定。这意味着每当选择一个下拉选项时,所有这些累积的lambda函数都将被执行,因此,每一个获得关注的TextInput都会更改其文本。

© www.soinside.com 2019 - 2024. All rights reserved.