Kivy - 通过引用根属性动态添加按钮

Posted

技术标签:

【中文标题】Kivy - 通过引用根属性动态添加按钮【英文标题】:Kivy - Add buttons dynamically with referring to root atributes 【发布时间】:2021-06-27 17:34:46 【问题描述】:

所以我尝试解决我的问题:

我有两个屏幕,当我从一个屏幕切换到另一个屏幕时,它应该在第二个屏幕上动态生成按钮(id:“thema_screen”)。这些按钮在第二个屏幕上创建为 GridLayout,其 id 为:“grid_thema_screen

现在,如果我更改窗口大小,我希望按钮的 font_size 自动更改,这与 kivy-file 中的font_size: min(root.height, root.width) / 10 效果很好,但是当我将其写入 python 文件 add_widget(Button(text = str(i+2), font_size = min(self.root.height, self.root.width) / 2))

它改变了一次字体大小,但是如果我重新调整窗口,字体就不再改变了。这是我的python文件的代码sn-p:

class Wurzel(MDBoxLayout):

def __init__(self, **kwargs):
    super(Wurzel, self).__init__(**kwargs)

def changeScreen(self, next_screen):
    if next_screen == "thema_screen":
        self.ids.wurzel_screen_manager.current = next_screen

        for i in range(12):
            self.ids.thema_screen.ids.grid_thema_screen.add_widget(Button(text = str(i+2), font_size = min(self.root.height,
                                                                                          self.root.width) / 10)) 

这里是我的 kivy 文件:

<Wurzel>:
orientation: 'vertical'
spacing: 20

MDToolbar:
    title: 'Hellllooo'
    left_action_items: [["menu", lambda x: app.navigation_klick()], ["apple", lambda x: app.navigation_klick()]]
    elevation: 8

ScreenManager:
    id: wurzel_screen_manager
    StartScreen:
        name: "start_screen"
    ThemaScreen:
        id: thema_screen
        name: "thema_screen"

<StartScreen@MDScreen>:

BoxLayout:
    orientation: "vertical"

   ...

<ThemaScreen@MDScreen>:
    GridLayout:
        id: grid_thema_screen
        cols: 3

    padding: root.width * .01, root.height * .01
    spacing: min(root.width, root.height) * .02


    Button:
        text: "1"
        font_size: min(root.height, root.width) / 10
        size_hint: None, None
        size: self.font_size*3, self.font_size*3

所以,如果有人可以帮助我并告诉我,如果我在 Python 中动态创建按钮,为什么字体大小不再自动更改,那就太好了。 非常感谢。

【问题讨论】:

【参考方案1】:

所以当您以编程方式添加按钮时字体大小不会改变的原因是因为font_size 属性没有绑定到任何东西。当您在 kv 文件中创建一个小部件时,解释器会自动将您的属性相互绑定。这意味着当您输入时:

font_size: min(root.height, root.width) / 10

在 kv 文件中,当 root.height 更新时,font_size 也会更新。但是,写

Button(font_size = min(self.root.height, self.root.width) / 2)

在您的 Python 文件中创建一个 Button,其 font_size 属性由您在该实例中传递的值定义。

您可以做几件事,您可以在您的 Wurzel 类中创建 NumericProperty 并将您的 Buttons 绑定到此属性(有关详细信息,请参阅 https://kivy.org/doc/stable/api-kivy.properties.html)。但是,由于您在调整大小时遇到​​问题,我认为最简单的方法是利用 on_size 回调(有关更多详细信息,请参阅 https://kivy.org/doc/stable/api-kivy.event.html)。

Wurzel 类应该是这样的:

class Wurzel(MDBoxLayout):

    def __init__(self, **kwargs):
        super(Wurzel, self).__init__(**kwargs)

    def changeScreen(self, next_screen):
        if next_screen == "thema_screen":
            self.ids.wurzel_screen_manager.current = next_screen

            for i in range(12):
                self.ids.thema_screen.ids.grid_thema_screen.add_widget(Button(text = str(i+2), font_size = min(self.root.height, self.root.width) / 10)) 

    def update_font_size(self, *args):
        for button in self.children:  # Loop through all children
            if isinstance(button, Button):  # Check if child is a button (may not need)
                button.font_size = min(self.root.height, self.root.width) / 10))  # Update font_size

    on_size = update_font_size  # Set a callback for on_size

【讨论】:

您好 jda5,非常感谢您的回答。我理解并尝试了您的代码,但我不确定将 on_size = update_font_size # Set a callback for on_size 部分放在哪里。我试图在 下的 kivy 文件中写 on_size: self.update_font_size():但它显示“声明后数据无效”。你能告诉我,在哪里写? 更新:我在“:”下添加了它,它还调用了 update_font_size 方法,但它并没有循环遍历我的所有按钮 :( 我认为是这样的,因为我的按钮创建的是“thema_screen”小部件的子级,而不是 Wurzel 小部件的子级。对吗?是否有可能到达所有按钮? 我通过接触 GridLayout 的子项(这是我的按钮...)找到了解决方案【参考方案2】:

所以我找到了 jda5 的解决方案(非常感谢你!!!)。我稍微改了一下@jda5的方法:

   def update_font_size(self, *args):
    for button in self.ids.thema_screen.ids.grid_thema_screen.children:  # Loop through all children
        
        if isinstance(button, Button):  # Check if child is a button (may not need)
            button.font_size = min(self.height, self.width) / 20  # Update font_size

然后我将“on_size”回调放到 kivy 文件中:

ScreenManager:
    id: wurzel_screen_manager
    StartScreen:
        name: "start_screen"
    ThemaScreen:
        on_size: app.root.update_font_size()
        id: thema_screen
        name: "thema_screen"

【讨论】:

以上是关于Kivy - 通过引用根属性动态添加按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何将纯 python 中动态创建的按钮添加到用 Kivy 语言编写的 kivy 布局中?

用python添加的kivy中的引用对象

如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色?

如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色?

如果未动态添加,如何正确删除Kivy中的小部件

引用 Kivy 中动态创建的小部件的 id