如何隐藏Kivy中的ActionButton?

pap*_*rin 4 python kivy

我试图相应地修改ActionButton对当前屏幕的可见性(使用屏幕管理器).我找不到可见属性或类似的东西,可以简单地切换可见性(对于ActionButton和一般的Widgets都没有).

2013年的帖子建议改变按钮的纹理,但我不想依靠这样的黑客来完成这么简单的任务,此外,我的应用程序的背景将是可变的.

另一篇文章建议删除小部件并根据需要再次添加.尽管它不必要复杂.我修改为在我的情况下工作(ActionBar和ActionButton),所以我从ActionView清除小部件,然后尝试添加ActionButton.我尝试存储weakref和self成员,我得到了以下错误:

WidgetException: Cannot add <kivy.uix.actionbar.ActionButton object at 0x7fcd3fe22ce8>, it already has a parent <kivy.uix.actionbar.ActionView object at 0x7fcd3fe22870>
Run Code Online (Sandbox Code Playgroud)

任何想法将不胜感激.我正在使用开发版,但它不适用于1.8.

编辑 我尝试了以下代码:

<AppActionBar>:
    ActionView:
        id: av

        ActionButton:
            id: btn_next
            text: 'Next screen'
            icon: 'data/icons/next_dark.png'
            important: True
            on_release: app.go_next()
Run Code Online (Sandbox Code Playgroud)

加载场景后运行此功能:

def _initialize(self):
  self.next = self.ids.btn_next.__self__ # same result if I don't use .__self__
Run Code Online (Sandbox Code Playgroud)

此代码引发了上面发布的异常:

self.ids.av.clear_widgets()
self.ids.av.add_widget(self.next)
Run Code Online (Sandbox Code Playgroud)

这是完整的异常跟踪:

     self._mainloop()
   File "/usr/local/lib/python2.7/dist-packages/kivy/core/window/window_pygame.py", line 266, in _mainloop
     EventLoop.idle()
   File "/usr/local/lib/python2.7/dist-packages/kivy/base.py", line 330, in idle
     Clock.tick_draw()
   File "/usr/local/lib/python2.7/dist-packages/kivy/clock.py", line 429, in tick_draw
     self._process_events_before_frame()
   File "/usr/local/lib/python2.7/dist-packages/kivy/clock.py", line 562, in _process_events_before_frame
     if event.tick(self._last_tick) is False:
   File "/usr/local/lib/python2.7/dist-packages/kivy/clock.py", line 309, in tick
     ret = callback(self._dt)
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/boxlayout.py", line 174, in do_layout
     c.width = w
   File "properties.pyx", line 345, in kivy.properties.Property.__set__ (kivy/properties.c:3589)
   File "properties.pyx", line 377, in kivy.properties.Property.set (kivy/properties.c:4064)
   File "properties.pyx", line 431, in kivy.properties.Property.dispatch (kivy/properties.c:4657)
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/actionbar.py", line 552, in on_width
     self._layout_all()
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/actionbar.py", line 441, in _layout_all
     super_add(child)
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/boxlayout.py", line 212, in add_widget
     return super(BoxLayout, self).add_widget(widget, index)
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/layout.py", line 78, in add_widget
     return super(Layout, self).add_widget(widget, index)
   File "/usr/local/lib/python2.7/dist-packages/kivy/uix/widget.py", line 466, in add_widget
     % (widget, parent))
 WidgetException: Cannot add <kivy.uix.actionbar.ActionButton object at 0x7fecb5d6ed50>, it already has a parent <kivy.uix.actionbar.ActionView object at 0x7fecb5d6e8d8>
Run Code Online (Sandbox Code Playgroud)

Spe*_*als 6

隐藏小部件比添加或删除小部件更好.只需将位置设置为包含屏幕外坐标:

# save the old y-coordinate of MyWidget.pos
root.saved_y = MyWidget.y
# Now move the widget offscreen (recall that pos is just an alias for (x, y))
MyWidget.y = 5000
Run Code Online (Sandbox Code Playgroud)

(我已经测试了这个解决方案;它有效.)


tot*_*ico 5

如果目标是隐藏小部件,则从父母中删除小部件不是一个好主意。当从Kivy树结构中删除某些内容时,垃圾收集器将对其进行拾取。您可以尝试保留对它的引用,但是从概念上讲,隐藏是不同于remove的

对我来说最好的解决方案是使用opacity属性。它与可见属性的原理相同,但功能更强大,因为它接受渐变(和动画)。

“ caveat”是您必须考虑到Widget仍然存在。它只是看不见的。在某些情况下,您可能想尝试将opacitydisabled属性结合使用。

Button:
    opacity: 0
    disabled: True # To make sure it doesn't capture events accidentally
Run Code Online (Sandbox Code Playgroud)


Oli*_*ver 1

我仍在学习 kivy,但令人惊讶的是,似乎没有属性或成员函数可以执行此操作。相反,您必须从其父级中删除该小部件,或将其颜色 alpha 设置为 0(这只适用于只有一种颜色的情况)。

更新

回溯表明调用self.next时仍然有父级。self.ids.av.add_widget(self.next)由于此调用之前有 a self.ids.av.clear_widgets(),因此仍在小部件树中的唯一方法self.next是它实际上不是 的子级self.ids.av。也许它是 所使用的默认布局的子级av,并且布局不会立即被垃圾收集。尝试

print 'next in av.children:', self.next in self.ids.av.children
print 'parent of next:', self.next.parent
# self.ids.av.clear_widgets()
# self.ids.av.add_widget(self.next)
parent = self.next.parent
parent.remove_widget(self.next)
parent.add_widget(self.next)
Run Code Online (Sandbox Code Playgroud)