【问题标题】:Kivy, StackLayout, object orderKivy,StackLayout,对象顺序
【发布时间】:2020-08-20 00:23:52
【问题描述】:

我有一个带有 StackLayout 的屏幕。堆栈的第一行包括一个文本输入和一个“+”按钮,该按钮旨在在循环中的实际行下方添加另一个相同的行(即另一个带有另一个“添加”按钮的文本输入)。然后有一个“保存”按钮,它应该总是在堆栈的末尾。 字典应该稍后在按下保存按钮时从文本字段中获取输入,但这应该与我的问题无关。

我的代码有两个问题:

  • 首先,当我连续按下“+”按钮时,突出显示的按钮不是此按钮本身,而是下一行中的那个(例如,如果有三行,我在第二行中按下按钮行,第三行的按钮高亮显示)
  • 其次,最重要的是,从第二行开始,每按一次“+”按钮,都会在实际行的上方而不是下方添加一个新行。

我知道 kivy 为小部件分配相反的顺序(即,最后添加的将首先绘制),这就是我手动为新行分配索引的原因。但是,我无法实现预期的行为。

这是一个最小的工作版本:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen

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

        self.grid = StackLayout()
        self.grid.pos_hint = {"x":0.05,"top":0.8}
        self.grid.size_hint = (0.9,None)
        self.add_widget(self.grid)

        self.i = 1
        self.n = 1
        self.inputs = {}
        self.ing1 = TextInput(size_hint=(0.9,'0.3sp'))
        self.grid.add_widget(self.ing1)
        self.inputs['0'] = 'ing1'

        self.addIng = Button(text="+", size_hint=(0.1,'0.3sp'))
        self.addIng.bind(on_press=self.addIngredient)
        self.grid.add_widget(self.addIng)

        self.doneButton = Button(text="Save")
        self.grid.add_widget(self.doneButton, index=0)

    def addIngredient (self, instance):
        self.ing = TextInput(size_hint=(0.9,'0.3sp'))
        self.inputs[self.i] = 'ing{}'.format(self.i+1)
        self.grid.add_widget(self.ing, index=self.n+1)

        self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
        self.addNext.bind(on_press=self.addIngredient)
        self.grid.add_widget(self.addNext, index=self.n+2)
        self.i += 1
        self.n += 2
        print(self.inputs)        

WMan = ScreenManager() 
WMan.add_widget(AddWindow(name='add'))


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

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

我错过了什么?为了更清楚,这是一个屏幕截图: Screenshot

【问题讨论】:

  • 新添加的行是否必须正好在按下Button 的行的下方?或者可以将新行添加到列表的末尾,但在 Save Button 上方?
  • 我想这并不重要,只要它低于它(事实上,它是一个配方成分列表,所以如果实际是一个新行,那么添加一个新行并没有真正的意义仍然是空的)。唯一的要求是保存按钮位于底部(实际上是在考虑将其从堆栈布局中取出并将其锚定到屏幕底部。好主意吗?)

标签: python kivy stacklayout


【解决方案1】:

这是一种蛮力方法,每次按下+`按钮时都重建StackLayout

def addIngredient(self, instance):
    tmp_children_list = self.grid.children[:]
    self.grid.clear_widgets()
    for index in range(len(tmp_children_list)-1, -1, -1):
        child = tmp_children_list[index]
        self.grid.add_widget(child)
        if child == instance:
            # this is the pressed Button, so add new row after it
            self.n += 1
            self.ing = TextInput(size_hint=(0.9,'0.3sp'))
            self.ing.text = str(self.n)  # add text just for identification
            self.grid.add_widget(self.ing)
            self.addNext = Button(text="+", size_hint=(0.1,'0.3sp'))
            self.addNext.bind(on_press=self.addIngredient)
            self.grid.add_widget(self.addNext)

【讨论】:

  • 我现在正在尝试使用 kv 文件来做同样的事情。虽然很明显如何添加“ing1”和“quant1”(默认显示的两个文本输入),但如何在 kv 中定义动态添加的行,以便它们仅在按下“+”按钮时出现?跨度>
  • 我认为这应该作为一个新问题发布。
【解决方案2】:

这是一种快速而肮脏的方法,由于删除和添加保存按钮,您的问题应该得到解决。在这些到操作之间,您在最终再次添加保存按钮之前添加一个新行。希望它可以帮助您调整代码。关键部分是 AddButton 的自定义 on_press 方法。

from kivy.app import App
from kivy.uix.stacklayout import StackLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.core.window import Window


class AddButton(Button):
    def __init__(self, **kwargs):
        super(AddButton, self).__init__(**kwargs)

    def on_press(self):
        self.parent.remove_widget(self.parent.save_btn)
        self.parent.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - self.parent.padding[1], Window.height * 0.1)))
        self.parent.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))
        self.parent.add_widget(self.parent.save_btn)


class MyApp(App):
    def build(self):
        Window.size = (400, 600)
        layout = StackLayout(orientation="lr-tb", padding=(20, 40))
        layout.save_btn = Button(text="Save", size_hint=(None, None),
                               size=(Window.width - layout.padding[1], Window.height * 0.1))

        layout.add_widget(TextInput(size_hint=(None, None), size=(Window.width * 0.8 - layout.padding[1], Window.height * 0.1)))
        layout.add_widget(AddButton(text="+", size_hint=(None, None), size=(Window.width * 0.2, Window.height * 0.1)))

        layout.add_widget(layout.save_btn)

        return layout

MyApp().run()

【讨论】:

  • 谢谢,这看起来也是一个不错的解决方案,但我发现约翰的答案更适合我的需求
猜你喜欢
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多