さまざまなビューを持つプログラムを作成しようとしています。
urwid を使用してさまざまなビューを処理するクラスを作成し、ビュー コードを残りから分離しようとしました。しかし、さまざまな試行錯誤の後、どこから始めればよいかわかりません。
画面をきれいに消去して再描画するには、どの urwid オブジェクトが必要ですか? また、ユーザー入力後にビューを切り替えることができるように、どのようにカプセル化する必要がありますか?
さまざまなビューを持つプログラムを作成しようとしています。
urwid を使用してさまざまなビューを処理するクラスを作成し、ビュー コードを残りから分離しようとしました。しかし、さまざまな試行錯誤の後、どこから始めればよいかわかりません。
画面をきれいに消去して再描画するには、どの urwid オブジェクトが必要ですか? また、ユーザー入力後にビューを切り替えることができるように、どのようにカプセル化する必要がありますか?
Urwidのドキュメントから:
MainLoop によって表示される最上位のウィジェットは、最初のパラメーターとしてコンストラクターに渡す必要があります。 実行中に最上位のウィジェットを変更する場合は、MainLoop オブジェクトの MainLoop.widget 属性に新しいウィジェットを割り当てることができます。これは、多数の異なるモードまたはビューを持つアプリケーションに役立ちます。
次に、いくつかのコードを示します。
import urwid
# This function handles input not handled by widgets.
# It's passed into the MainLoop constructor at the bottom.
def unhandled_input(key):
if key in ('q','Q'):
raise urwid.ExitMainLoop()
if key == 'enter':
try:
## This is the part you're probably asking about
loop.widget = next(views).build()
except StopIteration:
raise urwid.ExitMainLoop()
# A class that is used to create new views, which are
# two text widgets, piled, and made into a box widget with
# urwid filler
class MainView(object):
def __init__(self,title_text,body_text):
self.title_text = title_text
self.body_text = body_text
def build(self):
title = urwid.Text(self.title_text)
body = urwid.Text(self.body_text)
body = urwid.Pile([title,body])
fill = urwid.Filler(body)
return fill
# An iterator consisting of 3 instantiated MainView objects.
# When a user presses Enter, since that particular key sequence
# isn't handled by a widget, it gets passed into unhandled_input.
views = iter([ MainView(title_text='Page One',body_text='Lorem ipsum dolor sit amet...'),
MainView(title_text='Page Two',body_text='consectetur adipiscing elit.'),
MainView(title_text='Page Three',body_text='Etiam id hendrerit neque.')
])
initial_view = next(views).build()
loop = urwid.MainLoop(initial_view,unhandled_input=unhandled_input)
loop.run()
つまり、グローバル キー処理関数を使用して、ユーザーが押した特定のシーケンスをリッスンし、そのシーケンスを受け取ると、キー処理関数は MainView クラスで新しいビュー オブジェクトを作成し、loop.widget
そのオブジェクトに置き換えます。もちろん、実際のアプリケーションでは、すべてのユーザー入力に対してグローバルな unhandled_input 関数を使用するのではなく、ビュー クラスの特定のウィジェットにシグナル ハンドラーを作成する必要があります。connect_signal 関数については、こちらを参照してください。
Signal Functions ドキュメントのガベージ コレクションに関する部分に注意してください。多くのビューで何かを記述しようとしている場合、signal_handler が参照を保持するクロージャーであるため、ビューを置き換えた後でもそれらはメモリに残ります。そのため、weak_args
名前付き引数をurwid.connect_signal
関数に渡して、イベント ループでアクティブに使用されなくなったら、Urwid に渡すように指示する必要があります。