Ich stimme zu, dass der blinkende Cursor auf einem urwid.Button steht sieht ein bisschen lahm aus, also habe ich eine Lösung gefunden, um es zu verstecken. In urwid die Button Klasse ist nur eine Unterklasse von WidgetWrap mit SelectableIcon und zwei Text-Widgets (die umschließenden „<“ und „>“). Es ist die SelectableIcon -Klasse, die die Cursorposition standardmäßig auf das erste Zeichen der Bezeichnung setzt. Durch Unterklassen von SelectableIcon , ändern Sie die Cursorposition und packen Sie sie dann in einen urwid.WidgetWrap Unterklasse können Sie Ihre eigene benutzerdefinierte Schaltfläche erstellen, die alle Tricks eines integrierten Button ausführen kann , oder sogar noch mehr.
So sieht es in meinem Projekt aus.

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)
Als nächstes können Sie eine ButtonLabel umschließen Objekt zusammen mit allen anderen Objekten in einen WidgetWrap Unterklasse, die Ihre benutzerdefinierte Schaltflächenklasse sein wird.
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
In diesem Code gibt es eigentlich nicht viele Kombinationen von Widgets in FixedButton WidgetWrap Unterklasse, aber Sie könnten eine "[ hinzufügen " und "] " an den Rändern der Schaltfläche, wickeln Sie sie in LineBox ein usw. Wenn das alles überflüssig ist, können Sie die Ereignisbehandlungsfunktionen einfach in die ButtonLabel verschieben Klasse, und lassen Sie es ein Signal aussenden, wenn darauf geklickt wird.
Um die Schaltfläche umzukehren, wenn sich der Benutzer darauf bewegt, wickeln Sie sie in AttrMap ein und setze den focus_map zu einem Paletteneintrag ("button_reversed ", in meinem Fall).
urwid verwendet die Funktion curs_set, macht sie aber nirgendwo als Klassenmethode verfügbar. Jemand könnte urwid ändern, um die Verwendung dieser Methode zu ermöglichen; andernfalls gibt es dafür keine zuverlässige Methode.
Sie können es als Problem melden.
Aufbauend auf der Antwort von Drunken Master habe ich die Lösung so weit wie möglich bereinigt.
Die urwid.SelectableIcon ist im Grunde ein urwid.Text Feld mit diesem hässlichen blinkenden Cursor. Anstatt also den urwid.SelectableIcon zu überschreiben und in eine urwid.WidgetWrap packen , nehmen wir einen urwid.Text direkt und wählbar machen und auf Tasten-/Mausaktivierung reagieren (inspiriert von urwids einfachem Menü-Tutorial):
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()
Funktioniert wie ein Zauber:
