添加到 GridLayout 的 Button 小部件的 Kivy 实例在创建时缺少 pos 值?

Kivy Instance of Button widget added to GridLayout missing pos value on creation?

在我下面的 python/kivy 代码中,我尝试创建一个名为 mainMainWindow 的新实例(这是一个具有附加功能的 GridLayout),填充它带有 Button 小部件和 return 它在 MainApp.build().

我添加了一个 Debug 按钮,当按下按钮时打印 main 的所有 children 的 pos 值。

其他 Btn 按钮在按下时将打印 self.pos

build() 方法中,我在 returning main 之前打印 main 中所有 children 的位置。它确实显示了 children 的完整列表,但为所有 children 的 pos 值给出了 [0,0]。

但是,Btn 按钮的 on_release() 方法在调用时会给出正确的 self.pos 值。

有没有办法在初始化时为 main 的 children 获取正确的 pos 值,而不必调用 Btn [=54] 中的方法=]?

我怀疑这与 GridLayout 处理 Widget 定位的方式有关。

我已将 main 全局化以用于我正在处理的这个项目中的一些其他功能。我希望除了整个“你不应该使用全球价值观”之外,这不是一个大问题。

from kivy.app import App
from kivy.graphics import *
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window

class MainWindow(GridLayout): # main class
    def popbtns(self):
        i = 1
        while (i <= 29):
            self.add_widget(Btn(text='Btn #' + str(i) + ' at '+ str(self.pos)))
            i = i + 1

class Btn(Button): # button class
    def on_release(self):
        print('self.pos= ' + str(self.pos))

class Debug(Button): # debug button
    def on_release(self):
        for child in self.parent.children:
            print(str(child) + ' pos is ' + str(child.pos))

class MainApp(App):
    def build(self):

        global main
        main = MainWindow(cols=7)
        # make background
        with main.canvas:
            Rectangle(pos=main.pos, size=Window.size)

        # populate gridlayout with Buttons
        main.add_widget(Debug(text='debug',background_color=(1,0,0,1)))
        main.popbtns() 
        # print position of buttons...
        for child in main.children:
            print(str(child) + ' pos is ' + str(child.pos))
        return main

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

您试图在这些按钮放置在 window 上之前读取按钮的位置。它们位于 build 函数 returns 之后。要尽快读取这些位置,您需要一个单独的函数,该函数将在短暂的延迟后执行。使用 Clock 实现:

from kivy.clock import Clock
...
class MainApp(App):

    def build(self):

        main = MainWindow(cols=7)
        self.root = main  # don't use global!
        # make background
        with main.canvas:
            Rectangle(pos=main.pos, size=Window.size)

        # populate gridlayout with Buttons
        main.add_widget(Debug(text='debug', background_color=(1, 0, 0, 1)))
        main.popbtns()
        # print position of buttons...
        Clock.schedule_once(self.delayed_function, 0.1)            

    def delayed_function(self, dt):
        self.print_buttons_pos()

    def print_buttons_pos(self):
        for child in self.root.children:
            print(str(child) + ' pos is ' + str(child.pos))