Как ссылаться на идентификаторы kivy виджетов, динамически создаваемых с использованием языка kv через цикл for в основном файле python? - PullRequest
0 голосов
/ 31 октября 2019

Я динамически создавал виджеты ввода текста в файле .kv, используя язык kv. Однако я хотел бы установить текст в основном файле Python, используя цикл for, ссылаясь на их идентификаторы. Я написал следующий код:

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget

class setText(Widget):
    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        texts=['txtip1','txtip2']
        IDS=self.ids.keys()
        for i in range(IDS):
            self.ids[IDS[i]].text=texts[i]

class DocApp(App):        
    def build(self):
        return Builder.load_file("docapp\Doc.kv")
        return setText()

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

Doc.kv

# File: docapp.py
#: import TextInput kivy.uix.textinput.TextInput

GridLayout:
    cols:1
    on_kv_post:
        [self.add_widget(TextInput(id=str(i))) for i in range(2)]

Я искал другие вопросы, но не смог найти подходящего решения,Пожалуйста, помогите

Ответы [ 2 ]

0 голосов
/ 01 ноября 2019

Вы можете динамически создавать TextInput виджеты в kv, создавая kv динамически. Вот модификация вашего кода, которая делает это:

from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder


class DocApp(App):
    def build(self):
        # schedule the call to add the texts
        Clock.schedule_once(self.setText)

        # return the root widget from the kvString
        return layoutRoot

    def setText(self, dt):
        texts=['txtip1','txtip2']
        IDS=self.root.ids.keys()
        i = 0
        for id in IDS:
            self.root.ids[id].text=texts[i]
            i += 1


if __name__=="__main__":
    # Create the kv string here
    kvString = '''
GridLayout:
    cols:1
'''
    for i in range(2):
        kvString += '    TextInput:\n' + '        id: ' + str(i) + '\n'

    # Load the kv string
    layoutRoot = Builder.load_string(kvString)

    # and finally, run the App
    DocApp().run()

Я исключил класс setText (предполагая, что это был только держатель для метода setText), и поместил этот метод в App. Clock.schedule_once() планирует вызов на setText после создания App.

0 голосов
/ 31 октября 2019

Проблема в вашем коде в том, что id работает только в синтаксисе kv.
Так что вам нужно ссылаться на ваши виджеты другим способом.
В случае, если вам нужно сделать это таким образом, динамически добавляяв kv и доступе в цикле в python, вы можете попробовать что-то вроде примера ниже.
В этом случае текст изменится через 5 секунд. Если вы знаете, что единственными дочерними элементами этого вида сетки будут виджеты, к которым вы хотите получить доступ, вы можете просто повторить дочерние элементы.

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock

KV = """
#: import TextInput kivy.uix.textinput.TextInput

GridLayout:
    cols:1
    on_kv_post:
        for i in range(2): app.dynamic_widgets.append(TextInput())
        for wid in app.dynamic_widgets: self.add_widget(wid)

"""

class DocApp(App):
    dynamic_widgets = []

    def build(self):
        Clock.schedule_once(self.set_text, 5)
        return Builder.load_string(KV)

    def set_text(self, dt):
        texts=['txtip1','txtip2']
        for text, wid in zip(texts, self.dynamic_widgets):
            wid.text = text

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

Теперь, если вы удалите один из виджетов, вы, вероятно, захотитеудалить его из списка.

...