AttributeError: у объекта 'MyGrid' нет атрибута для моей функции - PullRequest
2 голосов
/ 11 июня 2019

Цель
Я пытаюсь создать простой скрипт, который демонстрирует, как прикрепить функцию к кнопке, которая может просматривать (и вскоре изменять) свойства другого виджета.Я знаю, что это возможно на основе примера сценария effectwidget.py .


Мои методы
В данный момент я пытаюсьобратный инжиниринг effectwidget.py, потому что он делает много вещей, которые я, вероятно, захочу сделать с kivy.

В effectwidget.py класс SpinnerRow имеет функцию с именем update_effectwidget(), которая может просматривать / редактироватьатрибуты конкретных экземпляров ComparisonWidget (который даже не является потомком SpinnerRow в дереве виджетов).SpinnerRow имеет дочерние виджеты EffectSpinner, которые вызывают update_effectwidget().

В моем сценарии 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() внутри моего ButtonHolder не обнаруживается, когдаон следует той же структуре, что и effectwidget.py ?

В целях охвата и управления для меня не практично давать каждому классу свои собственные функции, чтобы они могли вызываться самостоятельно.FunctionName ().И если root.functionName () вызывает функции только в самом корневом виджете (а не в родительских виджетах по пути), не означает ли это, что корневой виджет большой программы kivy должен будет содержать десятки функций?

Примечание: Самые близкие вопросы, которые я мог найти к этому, были Kivy 'объект не имеет атрибута' Ошибка и AttributeError: Объект 'Button' не имеет атрибута'update_label'.
Но их дела были слишком сложными и конкретными, чтобы найти ответ на мою общую проблему.Но я их видел.

1 Ответ

1 голос
/ 11 июня 2019

Ваше главное - незнание понятия корня. Чтобы лучше наблюдать, я выделил ваш код:

<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? принадлежит классу ButtonHolder, тогда корень должен быть изменен ссылкой на объект через идентификатор.

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