web-dev-qa-db-fra.com

Masquer et afficher un widget à Kivy

Je travaille sur un projet Kivy et je dois afficher une étiquette lorsqu'il n'y a aucun élément dans une liste. Sinon, je dois afficher une liste.

Voici les deux scénarios que je décris:

Quand aucun ami à montrer:  No friends

Quand la liste contient des amis:  List with friends

Ceci est mon fichier Kivy:

#: kivy 1.9.1
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import FriendItemButton gui.FriendItemButton

ChumMeRoot:

<ChumMeRoot>:
    friend_list_view: friend_list_view
    FriendList:
        id: friend_list_view


<FriendItemButton>:
    text: self.full_name
    height: "40dp"
    size_hint_y: None


<FriendList>:
    orientation: 'vertical'
    friend_list: friend_list_view
    Button:
        height: '45dp'
        size_hint_y: None
        text: 'Add Friend'
        on_press: app.root.show_add_friend_form()
    ListView:
        id: friend_list_view
        adapter:
            ListAdapter(
            data=[],
            cls=FriendItemButton,
            args_converter=root.args_converter)


<AddFriendFormInput@BoxLayout>
    height: '30dp'
    size_hint_y: None


<AddFriendForm>:
    orientation: 'vertical'
    first_name_input: first_name
    last_name_input: last_name
    AddFriendFormInput:
        Label:
            text: 'First Name'
        TextInput:
            id: first_name
    AddFriendFormInput:
        Label:
            text: 'Middle Name'
        TextInput:
    AddFriendFormInput:
        Label:
            text: 'Last Name'
        TextInput:
            id: last_name
    AddFriendFormInput:
        Label:
            text: 'Birthdate'
        TextInput:
    AddFriendFormInput:
        Label:
            text: 'Email'
        TextInput:
    AddFriendFormInput:
        Label:
            text: 'Cell Phone'
        TextInput:
    BoxLayout:
    BoxLayout:
        height: '40dp'
        size_hint_y: None
        Button:
            text: 'Cancel'
            on_press: app.root.show_friend_list()
        Button:
            text: 'Add friend'
            on_press: app.root.add_friend()

et voici mon code Python:

import os

from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.listview import ListItemButton

from friend import Friend
from friend_manager import FriendManager


def get_friend_manager():
    db_path = '{}/{}'.format(
        os.path.dirname(os.path.abspath(__file__)),
        'chumme.db'
    )
    return FriendManager(db_path)

def get_friends():
    return [(friend.full_name,)
            for friend in get_friend_manager().get_friends()]


class ChumMeRoot(BoxLayout):
    add_friend_form = ObjectProperty()
    friend_list_view = ObjectProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.update_friend_list_view()

    def update_friend_list_view(self):
        friend_list = self.friend_list_view.friend_list
        friend_list.adapter.data.clear()
        friend_list.adapter.data.extend(get_friends())
        friend_list._trigger_reset_populate()

    def show_add_friend_form(self):
        self.clear_widgets()
        self.add_friend_form = AddFriendForm()
        self.add_widget(self.add_friend_form)

    def show_friend_list(self):
        self.clear_widgets()
        self.update_friend_list_view()
        self.add_widget(self.friend_list_view)

    def add_friend(self):
        friend = Friend(first_name=self.add_friend_form.first_name_input.text,
                        last_name=self.add_friend_form.last_name_input.text)
        get_friend_manager().add_friend(friend)
        self.show_friend_list()


class AddFriendForm(BoxLayout):
    first_name_input = ObjectProperty()
    last_name_input = ObjectProperty()



class FriendList(BoxLayout):
    friend_list = ObjectProperty()

    def args_converter(self, index, data_item):
        return {'full_name': (data_item[0])}


class FriendItemButton(ListItemButton):
    full_name = StringProperty()


class ChumMeApp(App):
    pass


def main():
    ChumMeApp().run()


if __== '__main__':
    main()

Jusqu'à présent, j'ai trouvé cette solution qui dit essentiellement d'éviter de supprimer les widgets de la racine, et même si je l'ai essayée, j'ai perdu des références et mon application s'est bloquée. Je ne veux pas non plus placer l'élément dans une position en dehors de l'écran visible. Je me demande donc si quelqu'un connaît un moyen de masquer et d'afficher les widgets en tant que 'self.widget_name.hide () orself.widget_nom.hide = True`, ou quelqu'un peut-il me dire un bon moyen d'accomplir cette tâche?

7
lmiguelvargasf

Comme @yogabonito m'a suggéré de définir la hauteur du widget dans ce cas, 0dp (et évidemment l'attribut size_hint_y.

Voici les modifications apportées à mon fichier kivy:

<FriendList>:
    orientation: 'vertical'
    friend_list: friend_list_view
    no_friends_label: no_friends_label
    Button:
        height: '45dp'
        size_hint_y: None
        text: 'Add Friend'
        on_press: app.root.show_add_friend_form()
    Label:
        id: no_friends_label
    ListView:
        id: friend_list_view
        adapter:
            ListAdapter(
            data=[],
            cls=FriendItemButton,
            args_converter=root.args_converter)

Comme on peut le constater, j’ai ajouté un widget Label qui a dans sa racine une référence appelée no_friends_label.

Voici les modifications apportées à mon fichier Python:

class FriendList(BoxLayout):
    friend_list = ObjectProperty()
    no_friends_label = ObjectProperty()

    def args_converter(self, index, data_item):
        return {'full_name': (data_item[0])}

class ChumMeRoot(BoxLayout):
    add_friend_form = ObjectProperty()
    friend_list_view = ObjectProperty()

    # __init__ method

    def update_friend_list_view(self):
        friends = get_friends()
        no_friends_label = self.friend_list_view.no_friends_label
        friend_list = self.friend_list_view.friend_list

        if friends:
            friend_list.size_hint_y = 1
            friend_list.adapter.data.clear()
            friend_list.adapter.data.extend(friends)
            friend_list._trigger_reset_populate()
            no_friends_label.size_hint_y = None
            no_friends_label.height = '0dp'
            no_friends_label.text = ''
        else:
            no_friends_label = self.friend_list_view.no_friends_label
            no_friends_label.size_hint_y = 1
            no_friends_label.text = 'There are no friends to show.'
            friend_list.size_hint_y = None
            friend_list.height = '0dp'

     # remaining methods

Tout d'abord, j'ai ajouté la propriété kivy friend_list qui a la référence correspondante dans le fichier kivy. Ensuite, je "cache" ou affiche l'étiquette ou la vue liste en fonction des amis de l'utilisateur.

5
lmiguelvargasf

Devrait fonctionner pour chaque widget et cas d'utilisation:

def hide_widget(wid, dohide=True):
    if hasattr(wid, 'saved_attrs'):
        if not dohide:
            wid.height, wid.size_hint_y, wid.opacity, wid.disabled = wid.saved_attrs
            del wid.saved_attrs
    Elif dohide:
        wid.saved_attrs = wid.height, wid.size_hint_y, wid.opacity, wid.disabled
        wid.height, wid.size_hint_y, wid.opacity, wid.disabled = 0, None, 0, True
1
Matteljay