Urwid:使光标不可见

时间:2016-01-06 12:41:47

标签: python linux ncurses curses urwid

我正在使用urwid,这是一个Python"框架"用于在ncurses中设计终端用户界面。虽然我在urwid中无法在curses中轻松做到这一点,但是让光标不可见。就像现在一样,当选择按钮时光标是可见的,它看起来很丑陋。有没有办法禁用它?

4 个答案:

答案 0 :(得分:4)

我同意urwid.Button上闪烁的光标看起来有点蹩脚,所以我想出了一个隐藏它的解决方案。在urwid中,Button类只是WidgetWrap的子类,包含SelectableIcon和两个文本小部件(封闭的"<"和"> ;&#34)。默认情况下,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等。如果所有这些都是多余的,您可以将事件处理函数移动到ButtonLabel类中,并使其在发出信号时发出信号点击了。

要在用户移动按钮时使按钮反转,请将其包裹到AttrMap并将focus_map设置为某个调色板条目(" button_reversed",在我的情况下)。

答案 1 :(得分:2)

urwid使用curs_set函数,但不会将其作为类方法公开。有人可以修改urwid以允许使用此方法;否则就没有可靠的方法来做到这一点。

您可以将其报告为issue

答案 2 :(得分:1)

按照Drunken Master的回答,但用微创手术":

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)

在这里,我们只修改按钮的外观,否则保持其行为不变。

答案 3 :(得分:1)

根据醉拳大师的回答,我已尽可能多地清理解决方案。

urwid.SelectableIcon基本上是一个urwid.Text字段,带有一个难看的闪烁光标。 因此,与其直接覆盖urwid.SelectableIcon并将其打包到urwid.WidgetWrap中,不如让我们直接使用urwid.Text并将其设置为可选并响应按钮/鼠标激活:

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

像魅力一样工作:

enter image description here