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

问题描述 投票:0回答:3

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

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

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

这是我的代码:

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:
python kivy kivy-language
3个回答
9
投票

让我们看看输出:

'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
的字符会变成一个字符串key,值为object got from WeakProxy,指向WeakProxy指向的对象。或者更好地说:

id: value

成为

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

在哪里

value
变成一个object
print(self)
会返回什么)

我怀疑(不确定)如果你使用字符串作为

id
的值,你最终会得到 weakref / WeakProxy 指向一个字符串。我使用
point
这个词是因为它让我想起了指针,不要与 C 指针混淆。

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

  • super
    让您可以访问您继承自

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

因此如果你给id赋值一个

string
,你会遇到这样的情况:

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

虽然

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

(如有错误请指正)


3
投票

在定义 id 时不要使用引号。

id: uno

代替

id: 'uno'

0
投票

我在我的代码的两部分中发现了一个不必要的名称:名称,删除它们后代码可以正常工作

© www.soinside.com 2019 - 2024. All rights reserved.