【问题标题】:how to reference kivy widget ids dynamically created using kv language through a for loop in main python file?如何通过主python文件中的for循环引用使用kv语言动态创建的kivy小部件ID?
【发布时间】:2019-10-31 10:08:26
【问题描述】:

我使用 kv 语言在 .kv 文件中动态创建了 textinput 小部件。但是我想通过引用它们的 id 使用 for 循环在主 python 文件中设置文本。 我写了以下代码:

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()

文档.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)]

我已经搜索了其他问题,但找不到合适的解决方案。请帮忙

【问题讨论】:

  • 问题是你的TextInputs不是由kv lang添加的,而是由GridLayoutadd_widget()方法添加的。为了使 ids 可用,必须以 kv 样式 (id: theId) 添加它们。我已经看到这已完成,但找不到描述它的帖子。本质上,您将调用一个创建kv 字符串的方法,并使用Builder.load_string() 来加载它。这可以在 if __name__=="__main__": 块内完成,就在开始 App 之前。
  • 能否请您强调要在代码中进行哪些更改..谢谢

标签: python-3.x kivy kivy-language


【解决方案1】:

您的代码中的问题是 id 仅适用于 kv 语法。
因此,您需要以其他方式引用您的小部件。
如果您需要这样做,在 python 中动态添加 kv 并在循环中访问,您可以尝试类似下面的示例。
在这种情况下,文本将在 5 秒后更改。如果您知道此 gridlayout 的唯一子级将是您要访问的小部件,那么您不妨迭代这些子级。

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()

现在,如果您删除其中一个小部件,您可能还想将其从列表中删除。

【讨论】:

  • 谢谢它的工作...我只是想知道一件事 set_text 函数中传递的 dt 参数是什么?
【解决方案2】:

您可以通过动态创建kvkv 中动态创建TextInput 小部件。这是对您的代码的修改:

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 创建之后发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多