Kivy, StackLayout, порядок объектов - PullRequest
0 голосов
/ 05 мая 2020

У меня экран со StackLayout. Первая строка стека включает текстовый ввод и кнопку «+», которая предназначена для добавления еще одной идентичной строки под фактической строкой в ​​al oop (т.е. еще один текстовый ввод с другой кнопкой «добавить»). Затем есть кнопка «Сохранить», которая должна всегда находиться в конце стопки. Предполагается, что словарь позже захватит ввод из текстового поля при нажатии кнопки сохранения, но это не должно иметь отношения к моей проблеме.

Есть две проблемы с моим кодом:

  • Во-первых, когда я нажимаю кнопку «+» в строке, выделяется не эта кнопка, а кнопка в строке ниже (например, если есть три строки, и я нажимаю кнопку во втором строка, кнопка в третьей строке выделяется)
  • Во-вторых, и самое главное, начиная со второй строки и далее, каждое нажатие кнопки «+» добавляет новую строку над фактическим один, а не под ним.

Я знаю, что 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()

Что мне не хватает? Вот скриншот для большей наглядности: Скриншот

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Вот быстрый и грязный подход, при котором ваши проблемы должны быть исправлены из-за удаления и добавления кнопки сохранения. Между ними вы добавляете новую строку, прежде чем, наконец, снова добавите кнопку сохранения. Надеюсь, это поможет вам скорректировать код. Ключевой частью является настраиваемый метод on_press кнопки AddButton.

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()
0 голосов
/ 05 мая 2020

Вот метод грубой силы, позволяющий делать то, что вы хотите, перестраивая 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)
...