urwid.Button
のカーソルが点滅していることに同意します 少し不自由に見えるので、非表示にする解決策を考え出しました。 urwid では、Button
クラスは WidgetWrap
の単なるサブクラスです SelectableIcon
を含む および 2 つの Text ウィジェット (「<」と「>」で囲まれています)。 SelectableIcon
です デフォルトで、カーソル位置をラベルの最初の文字に設定するクラス。 SelectableIcon
をサブクラス化することにより 、カーソル位置を変更してから urwid.WidgetWrap
にラップします サブクラスを使用すると、組み込みのすべてのトリックを実行できる独自のカスタム ボタンを作成できます Button
、またはそれ以上。
これが私のプロジェクトでの外観です。
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
"、私の場合)。
urwid は curs_set 関数を使用しますが、どこにもクラス メソッドとして公開しません。誰かが urwid を変更して、このメソッドの使用を許可する可能性があります。そうでなければ、これを行う信頼できる方法はありません。
問題として報告してください。
Drunken Master の回答に基づいて、ソリューションを可能な限りクリーンアップしました。
urwid.SelectableIcon
基本的には urwid.Text
です この醜い点滅カーソルのあるフィールド。したがって、urwid.SelectableIcon
を上書きする代わりに そしてそれを urwid.WidgetWrap
に詰め込みます 、urwid.Text
を取りましょう 直接選択可能にし、ボタン/マウスのアクティブ化に反応します (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()
魔法のように機能します: