如何在 Kivy 中隐藏 ActionButton?

Posted

技术标签:

【中文标题】如何在 Kivy 中隐藏 ActionButton?【英文标题】:How to hide an ActionButton in Kivy? 【发布时间】:2014-06-06 07:53:52 【问题描述】:

我正在尝试根据当前屏幕修改 ActionButton 的可见性(使用屏幕管理器)。我找不到 Visible 属性或类似的东西可以简单地切换可见性(对于 ActionButton 和一般的小部件都不是)。

A post from 2013 建议更改按钮的纹理,但我不想依靠这样的 hack 来完成这样一个简单的任务,而且我的应用程序的背景会发生变化。

Another post 建议删除小部件并根据需要再次添加。尽管它不必要的复杂性。我修改为在我的情况下工作(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>

任何想法将不胜感激。我正在使用开发版本,但它不适用于 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()

该函数在场景加载后运行:

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

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

self.ids.av.clear_widgets()
self.ids.av.add_widget(self.next)

这是完整的异常跟踪:

     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>

【问题讨论】:

你能发一些你试过的代码吗? 当然,我添加了一个简短的示例。 @papirin - 如果您可以发布完整示例,我可能会为您提供帮助。一个正在运行的代码......我也遇到了一些按钮的此类问题,我修复了它。可能我们需要通过使用 try catch 或其他东西来进行调整(其他东西会比 try catch 更整洁):) @paarthbatra 非常感谢您查看此内容。我终于发现问题确实是 ActionView 处理其子项的方式中的一个错误,但此功能仍在开发中。等ActionBar稳定下来再看。 你也可以设置不透明度self.next.opacity = 0来隐藏按钮,设置self.next.opacity = 1来显示它虽然它可能不是你想要的,因为它只是让它透明。 【参考方案1】:

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

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

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

Button:
    opacity: 0
    disabled: True # To make sure it doesn't capture events accidentally

【讨论】:

您能举个例子吗? 按钮:id:button1 文本:'' 不透明度:0 大小:(0,0) 我添加一个示例,我正在调整大小为0,0,您可能不需要不透明度。如果size 不起作用,您应该先尝试size_hint Sup Tico,就我而言,我希望我的按钮出现并增长,因此不透明度和大小都可以使用动画来增长和缩小。【参考方案2】:

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

# 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

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

【讨论】:

如果您的小部件是例如,它将不起作用。 GridLayout 的子级。【参考方案3】:

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

更新

回溯表明self.next 在调用self.ids.av.add_widget(self.next) 时仍有父级。由于此调用之前有一个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)

【讨论】:

我贴的代码去掉了这个小部件,问题是我再次添加的时候出错了。【参考方案4】:

您可以尝试将 size_hint 设置为 0。我这样做是为了隐藏嵌套在 BoxLayout 中的布局。它完美无缺。另一种方法是从其父级中删除小部件。但是,如果您打算重新添加它,则需要再次实例化它。例如:

widget = Widget()
parent.add_widget(widget)
parent.remove_widget(widget)
# Create the widget again
widget = Widget()
parent.add_widget(widget)

【讨论】:

以上是关于如何在 Kivy 中隐藏 ActionButton?的主要内容,如果未能解决你的问题,请参考以下文章

在kivy中隐藏android键盘

访问 kivy 弹出父级

Kivy:如何使小部件表现得像溢出:隐藏

如何隐藏主窗口标题栏并在 kivy 框架中放置透明背景?

隐藏 Python Kivy TextInputs 的 Android 屏幕键盘

Kivy 小部件隐藏在 Windows 标题栏下