Kivy,弱引用对象不再存在

Posted

技术标签:

【中文标题】Kivy,弱引用对象不再存在【英文标题】:Kivy, weakly-referenced object no longer exists 【发布时间】:2018-08-28 06:48:12 【问题描述】:

这是我的kv文件

<GetAccount>:
    Button:
        id: refresh
        ang: 0
        background_normal: 'static/refresh.png'
        size_hint: None, None
        size: sp(50), sp(50)
        pos_hint: 'center_y': .96, 'center_x': .8 
        on_press: root.clean()
        canvas.before:
            Rotate:
                angle: self.ang
                origin: self.center

python代码中的一些逻辑和动态内容

class GetAccount(FloatLayout):

    keyandnick = ObjectProperty(KeyAndNick())
    account = ObjectProperty(Account())

    def __init__(self, **kargs):
        super(GetAccount, self).__init__(**kargs)
        layout = StackLayout(size_hint_y=None)
        layout.bind(minimum_height=layout.setter('height'))
        nicks = self.keyandnick.get_nicks()
        for nick in nicks:
            layout.add_widget(Button(text=str(nick[0]), size_hint_y=None, height=sp(60), on_press=self.ask_for_key))
        scroll = ScrollView(size_hint=(1, .9), bar_width=sp(5), bar_inactive_color=[.7, .7, .7, .5])
        scroll.add_widget(layout)
        self.add_widget(scroll)

    def ask_for_key(self, obj):
        self.clear_widgets()
        self.account_name = obj.text
        boxlayout = BoxLayout(size_hint=(1, .4), orientation='vertical', pos_hint='center_y': .5)
        self.key = TextInput(pos_hint='center_y': .5, hint_text='Key', font_size=sp(30), password=True)
        boxlayout.add_widget(self.key)
        boxlayout.add_widget(Button(text='Get Account', font_size=sp(30), on_press=self.get_account))
        boxlayout.add_widget(Button(text='Delete Account', pos_hint='center_x': .5, font_size=sp(30), on_press=self.delete_account))
        popup = Popup(title=self.account_name, content=boxlayout, size_hint=(1, .7))
        popup.bind(on_dismiss=self.clear)
        popup.open()

    def get_account(self, obj):
        if self.keyandnick.check_key(self.key.text):
            self.clear_widgets()
            boxlayout = BoxLayout(orientation='vertical', size_hint=(1, .6), pos_hint='center_y': .5)
            _account = self.account.get_account(self.account_name)
            a = True
            for data in _account:
                if a:
                    boxlayout.add_widget(Label(text=data, font_size=sp(30), bold=True, underline=True))
                    a = False
                else:
                    boxlayout.add_widget(Label(text=data, font_size=sp(20)))
            popup = Popup(title=self.account_name, content=boxlayout, size_hint=(1, .7))
            popup.open()
        else:
            self.key.background_color = [0, 0, 255, 0.3]

    def clean(self):
        animation = Animation(ang=360)
        animation.start(self.ids.refresh)
        animation.bind(on_complete=self.clear)

    def clear(self, a, b):
        self.clear_widgets()
        self.add_widget(GetAccount())

    def delete_account(self, obj):
        if self.keyandnick.check_key(self.key.text):
            self.account.delete_account(self.account_name)
            self.keyandnick.del_nick(self.account_name)
        else:
            self.key.background_color = [0, 0, 255, 0.3]

当我按下具有 id -> 刷新(在 kv 中定义)的按钮时,它工作正常,但第三次出现错误:

线程 Thread-1 中的异常:回溯(最近一次调用最后一次): _bootstrap_inner 中的文件“/usr/lib/python3.5/threading.py”,第 914 行 self.run() 文件“/usr/lib/python3.5/threading.py”,第 862 行,运行中 self._target(*self._args, **self._kwargs) 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/input/providers/mtdev.py”, 第 197 行,在 _thread_run _device = 设备(_fn)文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/lib/mtdev.py”, 第 131 行,在 init 中 self._fd = os.open(filename, os.O_NONBLOCK | os.O_RDONLY) PermissionError: [Errno 13] Permission denied: '/dev/input/event6' 动画=动画(ang=360)动画.开始(self.ids.refresh) animation.bind(on_complete=self.clear) 动画结束。 动画 = 动画(ang=360) 动画开始(self.ids.refresh) animation.bind(on_complete=self.clear) 动画结束。 [信息] [基地 ] 正在离开应用程序... Traceback (最近的调用 最后):文件“main.py”,第 146 行,在 AccountMaintainerApp().run() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/app.py”,行 824,运行中 runTouchApp() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/base.py”, 第 487 行,在 runTouchApp 中 EventLoop.window.mainloop() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/core/window/window_sdl2.py”, 第 525 行,在主循环中 self._mainloop() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/core/window/window_sdl2.py”, 第 290 行,在 _mainloop EventLoop.idle() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/base.py”, 第 327 行,空闲 Clock.tick() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/clock.py”, 第 483 行,刻度线 self._process_events() 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/clock.py”, 第 615 行,在 _process_events 中 event.tick(self._last_tick, remove) 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/clock.py”, 第 374 行,刻度线 ret = 回调(self._dt)文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/animation.py”, 第 342 行,在 _update 中 self.stop(小部件)文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/animation.py”, 213 号线,停止 self.cancel(widget) 文件“/home/ubuntu/.py-3.5.2/lib/python3.5/site-packages/kivy/animation.py”, 第 222 行,取消 self._widgets.pop(widget.uid, None) 文件“kivy/weakproxy.pyx”,第 19 行,在 kivy.weakproxy.WeakProxy.getattr (/tmp/pip-build-zy75v30v/kivy/kivy/weakproxy.c:1097) 文件 “kivy/weakproxy.pyx”,第 15 行,在 kivy.weakproxy.WeakProxy.ref (/tmp/pip-build-zy75v30v/kivy/kivy/weakproxy.c:1004) 参考错误: 弱引用对象不再存在

【问题讨论】:

见***.com/a/61777718 【参考方案1】:

Programming Guide » Kv language

id 是小部件的弱引用,而不是小部件本身。因此,存储 id 不足以防止小部件被垃圾收集。

要使小部件保持活动状态,必须保持对 id refresh 的直接引用。在这种情况下,这是使用 id.__self__refresh.__self__ 来实现的。

kv 文件

<GetAccount>:
    refresh: refresh.__self__
    Button:
        id: refresh
        ang: 0
        background_normal: 'static/refresh.png'
        size_hint: None, None
        size: sp(50), sp(50)
        pos_hint: 'center_y': .96, 'center_x': .8
        on_press: root.clean()
        canvas.before:
            Rotate:
                angle: self.ang
                origin: self.center

【讨论】:

好的,我明白了。当我按下这个具有 id 的按钮时,还有一件事:刷新整个内容会旋转,但我只是在 animation.start(self.ids.refresh) 中给出了按钮的 id,为什么会这样? Animation 和 AnimationTransition 用于为 Widget 属性设置动画。按钮的 id 是对按钮小部件的引用。因此,它会旋转按钮。 当时这对我有用,但是第二天,我运行了相同的程序,没有任何更改,并且发生了同样的错误

以上是关于Kivy,弱引用对象不再存在的主要内容,如果未能解决你的问题,请参考以下文章

Kivy Apk Buildozer:ReferenceError:弱引用对象不再存在

“弱引用对象不再存在”是啥意思?

弱引用

从python中的弱引用代理获取常规引用

WeakReference(弱引用)

强引用strong和弱引用weak的定义