AttributeError: 'MyGrid' object has no attribute for my function

AttributeError: 'MyGrid' object has no attribute for my function

目标
我正在尝试创建一个简单的脚本来演示如何将一个函数附加到一个按钮,该按钮可以查看(并很快更改)另一个小部件的属性。 我知道这是可能的,基于示例脚本 effectwidget.py.


我的方法
目前,我正在尝试逆向工程 effectwidget.py 因为它做了很多我可能想用 kivy 做的事情。

在 effectwidget.py 中,SpinnerRow class 有一个名为 update_effectwidget() 的函数,它可以 view/edit ComparisonWidget 的特定实例的属性(这甚至不是小部件树中 SpinnerRow 的子项)。 SpinnerRow 具有触发 update_effectwidget().

的子小部件 EffectSpinner 在我的脚本中,ButtonHolder 扮演 SpinnerRow 的角色,colorChange1() 扮演 update_effect() 的角色。

我的代码
此代码已缩减为仅显示可重现的错误。所以我不打算使用 this 来更改标签的颜色。

#!/usr/bin/env python3
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.uix.label import Label
from kivy.lang import Builder

class ButtonHolder(BoxLayout):
    def colorChange1(self, *args):
        print("this function works")

Builder.load_string("""
<MyGrid>:
  rows: 3
  Label:
    canvas.before:
      Color:
        rgba: 1,0,0,1
      Rectangle:
        pos: self.pos
        size: self.size
    id: toplabel
  Label:
    canvas.before:
      Color:
        rgba:  0,1,0,1
      Rectangle:
        pos: self.pos
        size: self.size
    id: bottomlabel
  ButtonHolder:
    Button:
      effectwidget: toplabel
      on_press: root.colorChange1()
""")

class MyGrid(GridLayout):
    pass

class TheApp(App):
    def build(self):
        return MyGrid()

TheApp().run()

问题
我收到以下错误:
AttributeError: 'MyGrid' object has no attribute 'colorChange1'

我想问你的问题

当我的函数 colorChange1() 遵循与 effectwidget.py 相同的结构时,为什么找不到我的 ButtonHolder 中的函数?

出于范围和管理的目的,为每个 class 提供自己的函数以便它们可以被 self.functionName() 调用对我来说是不切实际的。如果 root.functionName() 只调用最根部件(而不是沿途的任何父部件)中的函数,这是否意味着大型 kivy 程序的根部件必须包含许多函数?

注: 我能找到的最接近的问题是
但是他们的案例太复杂太具体,无法找到我的一般问题的答案。不过我见过。

你主要是对根的概念不了解。为了更好地观察它,我更好地缩进了您的代码:

<MyGrid>:
    rows: 3
    Label:
        id: toplabel
        canvas.before:
            Color:
                rgba: 1,0,0,1
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        id: bottomlabel
        canvas.before:
            Color:
                rgba:  0,1,0,1
            Rectangle:
                pos: self.pos
                size: self.size
    ButtonHolder:
        Button:
            effectwidget: toplabel
            on_press: root.colorChange1()

根是结构的初始元素,在本例中是 MyGrid。

MyGrid 有 colorChange1 方法吗?没有,这就是你得到那个错误的原因。

colorChange1方法属于什么class?属于ButtonHolderclass,那么root必须通过一个对象的引用来改变通过 id.

<MyGrid>:
    rows: 3
    Label:
        id: toplabel
        canvas.before:
            Color:
                rgba: 1,0,0,1
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        id: bottomlabel
        canvas.before:
            Color:
                rgba:  0,1,0,1
            Rectangle:
                pos: self.pos
                size: self.size
    ButtonHolder:
        id: button_holder # <---
        Button:
            effectwidget: toplabel
            on_press: button_holder.colorChange1() # <---