Urwid: сделать курсор невидимым

Я использую urwid, который является "фреймворком" Python для разработки терминальных пользовательских интерфейсов в ncurses. Однако есть одна вещь, которую я не могу сделать в urwid, что было легко в проклятиях - сделать курсор невидимым. Как и сейчас, курсор виден при выборе кнопок,и он просто выглядит уродливым. Есть ли способ отключить его?

3 ответов


urwid использует curs_set функция, но не предоставляет ее как метод класса в любом месте. Кто-то может изменить urwid, чтобы разрешить использование этого метода; в противном случае нет надежного способа сделать это.

вы можете сообщить об этом как вопрос.


я согласен, что мигающий курсор на urwid.Button выглядит немного коряво, поэтому я придумал решение, чтобы скрыть это. В urwid, в Button class - это просто подкласс WidgetWrap содержащий SelectableIcon и два текстовых виджета (Заключительные ""). Это SelectableIcon класс, который по умолчанию устанавливает позицию курсора на первый символ метки. По подклассам SelectableIcon, изменив положение курсора, а затем обернув его в urwid.WidgetWrap подкласс вы можете создать свою собственную кнопку это может сделать все трюки встроенный Button, или даже больше.

вот как это выглядит в моем проекте.

enter image description here

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)

Далее, вы можете обернуть ButtonLabel объект вместе с любыми другими объектами в WidgetWrap подкласс, который будет вашим пользовательским классом кнопок.

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

в этом коде на самом деле не так много комбинаций виджетов в FixedButton WidgetWrap подкласс, но вы можете добавить"[" и "]" по краям кнопки, оберните его в LineBox, etc. Если все это излишне, вы можете просто переместить функции обработки событий в ButtonLabel class, и сделать его испускать сигнал, когда он нажмет.

чтобы сделать кнопку обратной, когда пользователь перемещается по ней, оберните ее в AttrMap и выберите focus_map к некоторой записи палитры ("button_reversed", в моем случае).


по линии ответа Пьяного мастера, но с "минимально инвазивной хирургией":

class ButtonLabel(urwid.SelectableIcon):
    '''
    use Drunken Master's trick to move the cursor out of view
    '''
    def set_text(self, label):
        '''
        set_text is invoked by Button.set_label
        '''
        self.__super.set_text(label)
        self._cursor_position = len(label) + 1


class MyButton(urwid.Button):
    '''
    - override __init__ to use our ButtonLabel instead of urwid.SelectableIcon

    - make button_left and button_right plain strings and variable width -
      any string, including an empty string, can be set and displayed

    - otherwise, we leave Button behaviour unchanged
    '''
    button_left = "["
    button_right = "]"

    def __init__(self, label, on_press=None, user_data=None):
        self._label = ButtonLabel("")
        cols = urwid.Columns([
            ('fixed', len(self.button_left), urwid.Text(self.button_left)),
            self._label,
            ('fixed', len(self.button_right), urwid.Text(self.button_right))],
            dividechars=1)
        super(urwid.Button, self).__init__(cols)

        if on_press:
            urwid.connect_signal(self, 'click', on_press, user_data)

        self.set_label(label)

здесь мы только изменяем внешний вид кнопки, но в противном случае оставляем ее поведение неизменным.