Python - Kivy: AttributeError: 'super' object has no attribute '__getattr__' when trying to get self.ids

Python - Kivy: AttributeError: 'super' object has no attribute '__getattr__' when trying to get self.ids

我为一种 android 锁编写了代码,每当我尝试使用 id 获取特定的 ClickableImage 时,它​​都会引发以下错误:

AttributeError: 'super' object has no attribute '__getattr__'

我花了几个小时试图寻找这个问题的解决方案,我看了其他人有同样的问题,人们告诉他们更改构建器的站点,因为需要先调用它才能得到ids 属性或类似的东西,但每次我移动构建器时,它都会引发错误 "class not defined"。有什么线索吗?

这是我的代码:

from kivy.app import App
from kivy.config import Config
from kivy.lang import Builder
from kivy.graphics import Line
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior

#Variables
cords = ()
bld = Builder.load_file('conf.kv')

class Manager(ScreenManager): pass
class Principal(Screen): pass

class ClickableImage(ButtonBehavior, Image):
    def on_press(self):
        self.source = 'button_press.png'

    def on_release(self):
        self.source = 'button.png'
        self.ids.uno.source = 'button_press.png'

class canva(Widget):
    def on_touch_down(self, touch):
        global cords
        with self.canvas:
            touch.ud['line'] = Line(points=(touch.x, touch.y), width=1.5)
        cords = (touch.x, touch.y)

    def on_touch_move(self,touch):
        global cords
         touch.ud['line'].points = cords + (touch.x, touch.y)

    def on_touch_up(self,touch):
        self.canvas.clear()

class Api(App):    
    def build(self):
        return bld

if __name__ == '__main__':
    Api().run()

这是我的 .kv 文件:

# conf to file:  test.py

<Manager>:
    Principal:

<Principal>:
    GridLayout:
        size_hint_x: 0.5
        size_hint_y: 0.6
        width: self.minimum_width
        cols: 3
        ClickableImage:
            id: 'uno'
            size: 10,10
            source: 'button.png'
            allow_strech: True
        ClickableImage:
            id: 'dos'
            size: 30,30
            source: 'button.png'
            allow_strech: True
    canva:

让我们看看输出:

'super' object has no attribute '__getattr__'

在kv语言中id是以一种特殊的方式设置的(现在到1.9.2),它的值不是一个字符串,因为它不是一个偶然的变量。您无法使用 <widget>.id.

访问它

我会说它类似于 canvas,它不是小部件,但它可能看起来像那样(这就是为什么我对您的代码感到困惑 :P)。您已经注意到 something: <some object> 就像 Python 的 something = <object> 并且那是(至少我认为的)是 id 的值不是字符串的全部要点(这对某些人来说很奇怪)。如果 id 是一个字符串,则可能需要进行检查以将其以某种方式从随意赋值中排除。也许是因为性能或只是简单。

因此假设 id 是未来关键字的关键字。其实是的,因为分配给id的字符会变成一个字符串键,值为从WeakProxy得到的object,指向WeakProxy指向的对象。或者更好地说:

id: value

变成

<some_root_widget>.ids[str(value)] = weakref.proxy(value)

其中 value 成为一个 对象 print(self) 会 return)

我怀疑(不确定)如果您使用字符串作为 id 的值,您最终会得到指向字符串的 / WeakProxy。我使用 point 这个词是因为它让我想起指针,不要与 C 指针混淆。

现在,如果您再次查看输出:

  • super 使您可以访问继承自

  • 的 class
  • print('string id'.__getattr__) 会给你同样的错误,但是 'super' 被替换为实际值,因为......它没有 __getattr__

因此如果你将一个字符串值赋给id,你会遇到这种情况:

<some_root_widget>.ids[str('value')] = weakref.proxy('value')  # + little bit of magic

虽然 str('value') 不一定是错误的,但默认情况下您不能为字符串创建 weakref.proxy。我不确定 Kivy 如何使用 Wea​​kProxies 处理这个问题,但是如果你将一个字符串分配给 id,大致就是你得到的。

(如有错误请指正)

定义 ID 时不要使用引号。

id: uno

而不是

id: 'uno'