Динамическое управление вкладками KivyMD с различными «итерациями» вкладок

#python #kivy #kivymd

#python #kivy #kivymd

Вопрос:

Я использовал код из документов KivyMD о «Динамическом управлении вкладками», чтобы пользователи могли добавлять / удалять вкладки. Однако каждая из этих созданных вкладок, очевидно, идентична, и поэтому виджеты, которые я в нее помещаю, тоже. Это означает, что если я пытаюсь взять идентификатор указанного виджета из, например, вкладки 3, нет способа сделать это, поскольку это тот же идентификатор, что и у виджета на, например, вкладке 1. Вот код:

файл .py

 def on_start(self):
    self.add_tab()

def get_tab_list(self):
    print(self.root.ids.addworkouts.ids.tabs.get_tab_list())

def add_tab(self):
    self.index  = 1
    self.root.ids.addworkouts.ids.tabs.add_widget(Tab(text=f"Exercise {self.index}"))

def remove_tab(self):
    self.index -= 1
    self.root.ids.addworkouts.ids.tabs.remove_widget(
        self.root.ids.addworkouts.ids.tabs.get_tab_list()[0]
    )
  

файл .kv

 <AddWorkouts>
name: 'AddWorkouts'
tabs: tabs

BoxLayout:
    orientation: 'vertical'

    MDToolbar:
        title: ' '#app.getWorkoutName()
        type: 'top'
        left_action_items: [['keyboard-backspace', lambda x: app.goBacktoMyWorkouts()]]
        #md_bg_color: app.theme_cls.accent_color
        elevation: 10


    FloatLayout:
        canvas:
            Color:
                rgba: 0, 0, 0.5, 0.9
            Rectangle:
                pos: self.pos
                size: self.size

        MDTabs:
            id: tabs

        FloatLayout:
            canvas:
                Color:
                    rgba: 1, 1, 1, 1
                Rectangle:
                    size: self.size
                    pos: self.pos

            pos_hint: {'center_x': 0.5, 'y': 0.1}
            size_hint: 0.8, 0.6


            MDTextField:
                pos_hint: {'x': 0.05, 'y': 0.8}
                size_hint: 0.6, None
                hint_text: 'Exercise Name'
                helper_text_mode: 'on_focus'
                required: 'True'
                multiline: False


<Tab>

    MDList:

        MDBoxLayout:
            adaptive_height: True
            md_bg_color: 1, 1, 1, 1

            MDFlatButton:
                text: "ADD EXERCISE"
                text_color: 16/255, 167/255, 249/255, 1
                on_release: app.add_tab()

            MDFlatButton:
                text: "REMOVE LAST EXERCISE"
                text_color: 16/255, 167/255, 249/255, 1
                on_release: app.remove_tab()
  

Вкладка 1, где входные данные в MDTextField ‘Hi’:

введите описание изображения здесь

Tab2, где входные данные в MDTextField дублируются с Tab:

введите описание изображения здесь Есть ли возможность по-прежнему предоставлять пользователям возможность добавлять и удалять вкладки, но сделать так, чтобы все виджеты (например, MDTextField в файле .kv) имели разные идентификаторы, чтобы я мог получить доступ к пользовательскому вводу из них? Заранее благодарю вас, если этот вопрос был сформулирован неправильно, пожалуйста, просто запросите дополнительную информацию!

Ответ №1:

ids Заполняются только для виджетов, созданных в kv правиле. Таким образом, любое, Tab созданное вне .kv файла, не будет введено в ids словарь. Однако вы можете взломать их, ids изменив свой add_tab() метод:

 import weakref
def add_tab(self):
    self.index  = 1
    new_tab = Tab(text=f"Exercise {self.index}")
    new_id = 'tab_'   str(self.index)
    self.root.ids.addworkouts.ids.tabs.add_widget(new_tab)
    self.root.ids.addworkouts.ids.tabs.ids[new_id] = weakref.ref(new_tab)
  

Это добавляет new_id к ids в MDTabs .

Чтобы сделать это MDTextField частью Tab , просто добавьте это в <Tab> правило. Возможно, вот так:

 <Tab>
    MDList:
        MDTextField:
            size_hint: 0.6, None
            hint_text: 'Exercise Name'
            helper_text_mode: 'on_focus'
            required: 'True'
            multiline: False

        MDBoxLayout:
            adaptive_height: True
            md_bg_color: 1, 1, 1, 1

            MDFlatButton:
                text: "ADD EXERCISE"
                text_color: 16/255, 167/255, 249/255, 1
                on_release: app.add_tab()

            MDFlatButton:
                text: "REMOVE LAST EXERCISE"
                text_color: 16/255, 167/255, 249/255, 1
                on_release: app.remove_tab()
  

Конечно, вы бы удалили MDTextField (и его окружение FloatLayout ) из <AddWorkouts> правила.

Комментарии:

1. Это работает, но входные данные в MDTextField по-прежнему дублируются между вкладками. Если я введу «Привет» в текстовое поле на вкладке 1, а затем добавлю другую вкладку, сообщение скопируется. Как мне изменить это, чтобы каждая новая итерация вкладки «обновляла» виджеты?

2. MDTextField Это не в Tab , это в FloatLayout внутри AddWorkouts Screen . Таким образом, изменение вкладок никак на это не влияет. Это не дублируется, это просто не является частью Tab .

3. А, ладно, это имеет гораздо больше смысла. Итак, что я хочу, так это отдельные плавающие описания для каждой вкладки, чтобы MDTextField отличался? Как бы я это сделал?

4. спасибо @JohnAnderson, я закрываюсь, чтобы решить ту же проблему, но получаю эту ошибку » Ошибка атрибута: объект ‘MainApp’ не имеет атрибута ‘index’