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: