7

一種の 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:
4

2 に答える 2

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文字は、WeakProxy から取得したオブジェクトの値を持つ文字列キーになるため、WeakProxy が指すオブジェクトになります。またはより良い言い方:

id: value

になる

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

どこvalueオブジェクトになるか(何print(self)が返されるか)

の値として string を使用すると、 weakref / WeakProxyが文字列を指すことになるidと思います (よくわかりません)。私はポインターを思い出させるので、この言葉を使用します。C ポインターと混同しないでください。point

出力をもう一度見ると、次のようになります。

  • super継承元のクラスへのアクセスを提供します

  • 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 が WeakProxies でこれをどのように処理するかはわかりませんが、文字列を に割り当てるとid、おおよそこれが得られます。

(間違っていたら訂正してください)

于 2016-08-25T18:35:45.767 に答える