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

Kivy - Add buttons dynamically with referring to root atributes

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

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

现在,如果我更改 window 大小,我希望按钮的 font_size 自动更改,这与 kivy 中的 font_size: min(root.height, root.width) / 10 配合得很好-file,但是当我在 python-file add_widget(Button(text = str(i+2), font_size = min(self.root.height, self.root.width) / 2))

中写入时,它不起作用

它改变了一次字体大小,但如果我重新设置 window,字体就不再改变了。这是我的 python 文件的代码片段:

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 中动态创建按钮,为什么字体大小不再自动更改,那就太好了。 非常感谢。

所以当您以编程方式添加按钮时字体大小没有改变的原因是因为 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 文件中创建一个按钮,其 font_size 属性由您在该实例中传递的值定义。

您可以做几件事,您可以在 Wurzel class 中创建 NumericProperty 并将按钮绑定到此 属性(请参阅 https://kivy.org/doc/stable/api-kivy.properties.html for more details). However, since your having the issues with resizing, I think the easiest thing to do is take advantage of the on_size call back (see https://kivy.org/doc/stable/api-kivy.event.html了解更多详情)。

Wurzel class 应该是这样的:

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 的解决方案(非常感谢你!!!)。我把@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"