GNU/Linux >> Tutoriels Linux >  >> Linux

Urwid :rendre le curseur invisible

Je suis d'accord que le curseur clignotant sur un urwid.Button semble un peu boiteux, alors j'ai trouvé une solution pour le cacher. En urwid, le Button la classe est juste une sous-classe de WidgetWrap contenant un SelectableIcon et deux widgets Texte (les "<" et ">" englobants). C'est le SelectableIcon classe qui définit la position du curseur sur le premier caractère de l'étiquette, par défaut. En sous-classant SelectableIcon , en modifiant la position du curseur puis en l'enveloppant dans un urwid.WidgetWrap sous-classe vous pouvez créer votre propre bouton personnalisé qui peut faire toutes les astuces d'un Button intégré , ou même plus.

Voici à quoi cela ressemble dans mon projet.

import urwid

class ButtonLabel(urwid.SelectableIcon):
    def __init__(self, text):
        """
        Here's the trick: 
        we move the cursor out to the right of the label/text, so it doesn't show
        """
        curs_pos = len(text) + 1 
        urwid.SelectableIcon.__init__(self, text, cursor_position=curs_pos)

Ensuite, vous pouvez envelopper un ButtonLabel objet avec tous les autres objets dans un WidgetWrap sous-classe qui sera votre classe de boutons personnalisés.

class FixedButton(urwid.WidgetWrap):
    _selectable = True
    signals = ["click"]
    def __init__(self, label):
        self.label = ButtonLabel(label)
        # you could combine the ButtonLabel object with other widgets here
        display_widget = self.label 
        urwid.WidgetWrap.__init__(self, urwid.AttrMap(display_widget, None, focus_map="button_reversed"))

    def keypress(self, size, key):
        """
        catch all the keys you want to handle here
        and emit the click signal along with any data 
        """
        pass

    def set_label(self, new_label):
        # we can set the label at run time, if necessary
        self.label.set_text(str(new_label))

    def mouse_event(self, size, event, button, col, row, focus):
        """
        handle any mouse events here
        and emit the click signal along with any data 
        """
        pass

Dans ce code, il n'y a en fait pas beaucoup de combinaisons de widgets dans le FixedButton WidgetWrap sous-classe, mais vous pouvez ajouter un "[ " et "] " sur les bords du bouton, enveloppez-le dans un LineBox , etc. Si tout cela est superflu, vous pouvez simplement déplacer les fonctions de gestion des événements dans le ButtonLabel class, et lui faire émettre un signal lorsqu'il est cliqué.

Pour inverser le bouton lorsque l'utilisateur se déplace dessus, enroulez-le dans AttrMap et définissez le focus_map à une entrée de palette ("button_reversed ", dans mon cas).


urwid utilise la fonction curs_set, mais ne l'expose nulle part en tant que méthode de classe. Quelqu'un pourrait modifier urwid pour permettre l'utilisation de cette méthode; sinon, il n'y a pas de méthode fiable pour le faire.

Vous pouvez le signaler comme un problème.


En m'appuyant sur la réponse de Drunken Master, j'ai nettoyé la solution autant que possible.

Le urwid.SelectableIcon est fondamentalement un urwid.Text champ avec ce vilain curseur clignotant. Ainsi, au lieu de remplacer le urwid.SelectableIcon et de l'emballer dans un urwid.WidgetWrap , prenons un urwid.Text directement et rendez-le sélectionnable et réagissez à l'activation du bouton/de la souris (inspiré du didacticiel de menu simple d'urwid):

import urwid

choices = u'Chapman Cleese Gilliam Idle Jones Palin'.split()

class ListEntry(urwid.Text):
    _selectable = True

    signals = ["click"]

    def keypress(self, size, key):
        """
        Send 'click' signal on 'activate' command.
        """
        if self._command_map[key] != urwid.ACTIVATE:
            return key

        self._emit('click')

    def mouse_event(self, size, event, button, x, y, focus):
        """
        Send 'click' signal on button 1 press.
        """
        if button != 1 or not urwid.util.is_mouse_press(event):
            return False

        self._emit('click')
        return True

def menu(title, choices):
    body = [urwid.Text(title), urwid.Divider()]
    for c in choices:
        button = ListEntry(c)
        urwid.connect_signal(button, 'click', item_chosen, c)
        body.append(urwid.AttrMap(button, None, focus_map='reversed'))
    return urwid.ListBox(urwid.SimpleFocusListWalker(body))

def item_chosen(button, choice):
    response = urwid.Text([u'You chose ', choice, u'\n'])
    done = ListEntry(u'Ok')
    urwid.connect_signal(done, 'click', exit_program)
    main.original_widget = urwid.Filler(urwid.Pile([response,
                                                    urwid.AttrMap(done, None, focus_map='reversed')]))

def exit_program(button):
    raise urwid.ExitMainLoop()

main = urwid.Padding(menu(u'Pythons', choices), left=2, right=2)
top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
                    align='center', width=('relative', 60),
                    valign='middle', height=('relative', 60),
                    min_width=20, min_height=9)
urwid.MainLoop(top, palette=[('reversed', 'standout', '')]).run()

Fonctionne comme un charme :


Linux
  1. Faire défiler les mouvements de la souris lorsque le bouton du milieu est maintenu enfoncé ?

  2. Linux – Comment rendre un processus invisible pour les autres utilisateurs ?

  3. Créer un binaire statique ?

  4. Définir la transparence de la fenêtre dans Gnome ?

  5. Comment faire en sorte que le bouton du terminal Unity ouvre un terminal séparé?

Faire de la musique sur Linux avec Ardour

Créer une clé USB persistante Kali Linux

Bash Select (créer des menus)

Comment rendre un fichier exécutable sous Linux

Utiliser l'éditeur vi

PiShrink - Rendre les images Raspberry Pi plus petites