¿Cómo ocultar un ActionButton en Kivy?

Estoy tratando de modificar la visibilidad de un ActionButton de acuerdo con la pantalla actual (usando el Administrador de pantalla). No pude encontrar una propiedad visible o algo por el estilo que pueda simplemente cambiar la visibilidad (ni para ActionButton ni para Widgets en general).

Una publicación de 2013 sugiere cambiar la textura del botón, pero no quiero confiar en un truco para realizar una tarea tan simple, además, el fondo de mi aplicación será variable.

Otra publicación sugiere eliminar el widget y agregarlo nuevamente según sea necesario. A pesar de su complejidad innecesaria. Me modifiqué para trabajar en mi caso (ActionBar y ActionButton), así que borro los widgets de ActionView y luego bash agregar el ActionButton. Intenté almacenar un miembro débil y uno mismo , con ambos obtuve el siguiente error:

WidgetException: Cannot add , it already has a parent  

Cualquier idea sería muy apreciada. Estoy trabajando con la versión dev, pero tampoco funciona con 1.8.

EDITAR He intentado el siguiente código:

 : ActionView: id: av ActionButton: id: btn_next text: 'Next screen' icon: 'data/icons/next_dark.png' important: True on_release: app.go_next() 

Esta función se ejecuta después de cargar la escena:

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

Este código plantea la excepción publicada anteriormente:

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

Aquí está la traza completa de la excepción:

  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 , it already has a parent  

Hay una mejor manera de ocultar los widgets que agregarlos o eliminarlos. Simplemente configura la posición para incluir una coordenada fuera de pantalla:

 # 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 

(He probado esta solución; funciona.)

Eliminar los widgets de los padres no es una buena idea, si el objective es ocultarlos. Cuando se retira algo de la estructura del árbol Kivy, el recolector de basura lo recogerá. Podría intentar mantener una referencia a él, pero conceptualmente esconderse es diferente de eliminar .

La mejor solución para mí ha sido usar la propiedad de opacidad. Es el mismo principio de una propiedad visible, pero más poderoso porque acepta gradientes (y animaciones).

La “advertencia” es que debe tener en cuenta que el Widget todavía está allí . Es simplemente invisible. En algunos casos, es posible que desee probar y combinar la opacity con la propiedad disabled .

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

Todavía estoy aprendiendo kivy pero parece que, sorprendentemente, no hay ninguna propiedad o función miembro para hacer esto. En su lugar, debe eliminar el widget de su padre o establecer su color alfa en 0 (que solo funcionará en los casos en que tenga un color).

Actualización :

El rastreo indica que self.next todavía tiene un padre cuando se self.ids.av.add_widget(self.next) . Dado que esta llamada está precedida por self.ids.av.clear_widgets() , la única forma en que self.next aún está en el árbol de widgets es que en realidad no es un hijo de self.ids.av Tal vez sea un elemento secundario del diseño predeterminado utilizado por av , y el diseño no se recolecta inmediatamente. Tratar

 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) 

Podría intentar establecer size_hint en 0. Hice esto para ocultar un diseño que estaba nested dentro de un BoxLayout. Funcionó a la perfección. Otro método es eliminar el widget de su padre. Pero si planea volver a agregarlo, debe crear una instancia de nuevo. Por ejemplo:

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

He implementado ambas soluciones en un proyecto en el que estoy trabajando. Puedes consultar el código fuente.

luces.py