Skip to content

Introduction to Widgets

ウィジェットは、Ratatuiのユーザーインターフェイスの構成要素です。それらは、ターミナルインターフェイスのレイアウトとスタイルを作成および管理するために使用されます。ウィジェットを組み合わせてネストして複雑なUIを作成することができ、アプリケーションのニーズに合わせて簡単にカスタマイズできます。

Ratatuiは、UISをすばやく作成するために使用できるさまざまな内蔵ウィジェットを提供します。これらのウィジェットには次のものが含まれます。

さらに、[String], [&str], [Span], [Line], [Text] はウィーゲットとして使用できます (ただし、これらの直接の代わりに Paragraph を使用することは一般的です) 。

これらのウィジェットの詳細については、[ウィジェットAPI Docs] [Widgets-Docs]と[Widget Showcase] [Showcase]を表示できます。さらに、Ratatuiで使用できるサードパーティのウィジェットがいくつかあります。これは、[サードパーティのウィジェットショーケース] [サードパーティ-widgets]および[Awesome Ratatui]リポジトリにあります。

ウィジェットtrait

Ratatuiでは、ウィジェットがRust trait として実装されており、実装と拡張が容易になります。ウィジェットの2つの主なtrait は、[Widget]と[StatefulWidget]です。これは、ウィジェットの状態をレンダリングおよび管理するための基本的な機能を提供します。

さらに、[WidgetRef]および[StatefulWidgetRef]trait により、ウィジェットを参照してレンダリングすることができます。これは、ウィジェットのコレクションを保存およびレンダリングするのに役立ちます。後者の2つのtrait は、Ratatui 0.26に追加され、執筆時点で、不安定な特徴フラグで格付けされているため、これらのtrait の第三者の使用は限られている可能性があります。すべての内部ウィジェットがREFtrait を実装するために更新されており、 Widget for &T where T: WidgetRef のブランケット実装もあります。

ウィジェット

[Widget]trait は、Ratatuiのウィジェットの最も基本的なtrait です。ウィジェットをバッファーにレンダリングするための基本的な機能を提供します。

pub trait Widget {
fn render(self, area: Rect, buf: &mut Buffer);
}

Statefulwidget

[StatefulWidget]trait は、[Widget]trait に似ていますが、レンダリング中に管理および更新できる状態も含まれます。

pub trait StatefulWidget {
type State;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

WidgetRefとStateful Widget Ref

[WidgetRef]trait により、ウィジェットを消費する代わりに参照ごとにウィジェットをレンダリングできます。これは、個人やコレクションの保存とレンダリングに役立ちます。

[StatefulWidgetRef]trait は、[WidgetRef]trait に似ていますが、レンダリング中に管理および更新できる状態も含まれます。

これらの2つのtrait は、Ratatui 0.26.0で導入され、以前にその仮定で構築されたすべてのコードを壊すわけではなく、ウィジェットが常にレンダリングで消費されることを意味する欠点を避けるのに役立ちました。これらの2つのウィジェットは現在、不安定であるとマークされており、 unstable-widget-ref 機能フラグの背後にゲートされています。

pub trait WidgetRef {
fn render_ref(&self, area: Rect, buf: &mut Buffer);
}
pub trait StatefulWidgetRef {
type State;
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

ウィジェットを使用します

Ratatuiでは、ターミナルインターフェイスのレイアウトとスタイルを作成および管理するためにウィジェットが使用されます。ウィジェットを組み合わせてネストして複雑なUIを作成することができ、アプリケーションのニーズに合わせて簡単にカスタマイズできます。

アプリケーションでウィジェットを使用するには、通常、[Frame]タイプを使用します。これには、ウィジェットをレンダリングする2つの方法があります: [render_widget]と[render_stateful_widget] (および対応する _ref メソッド) 。これらのメソッドは、ウィジェットを描画するアプリケーションのエントリポイントであり、通常、[Terminal::draw]メソッドに渡される閉鎖から呼び出されます。

render_widget メソッドを使用してウィジェットを描画する例は次のとおりです。

terminal.draw(|frame| {
frame.render_widget(some_widget, frame.area());
});

そして、 render_stateful_widget メソッドを使用してStatefulwidgetを描画する例を次に示します。

terminal.draw(|frame| {
frame.render_stateful_widget(some_stateful_widget, frame.area(), &mut some_state);
});

これらの方法は、[Widget]または[StatefulWidget]のtrait の render 関数を内部的に呼び出します。

一般的な構成パターンは、 Frame::render_widget() に渡され、その後のウィジェット内で渡される単一のルートウィジェット (以下の例の App struct) のみを持っていることです。ウィジェットへ。

#[derive(Default)]
struct App {
// ...
should_quit: bool
}
fn main() {
let app = App::default();
// ...
while !app.should_quit {
terminal.draw(|frame| {
frame.render_widget(&app, frame.area())
})
}
}
impl Widget for &App {
fn render(self, area: Rect, buf: &mut Buffer) {
// ...
MyHeaderWidget::new("Header text")
.render(Rect::new(0, 0, area.width, 1), buf);
}
}

ウィジェットの実装

Ratatuiでは、ウィジェットがRust trait として実装されており、実装と拡張が容易になります。ウィジェットの2つの主なtrait は、[Widget]と[StatefulWidget]です。これは、ウィジェットの状態をレンダリングおよび管理するための基本的な機能を提供します。

簡単なグリーティングウィジェットの[Widget]のtrait を実装する例を次に示します。

struct GreetingWidget {
name: String,
}
impl Widget for GreetingWidget {
fn render(self, area: Rect, buf: &mut Buffer) {
let greeting = format!("Hello, {}!", self.name);
buf.set_string(area.x, area.y, greeting, Style::default());
}
}

この例では、 GreetingWidget structには、 String である単一のフィールド name があります。 render 関数は、 RectBuffer への可変参照を取り、バッファ内の指定された座標に文字列を設定します。

ウィジェットは、 Buffer でメソッドを呼び出すだけに制限されていません。また、 render メソッド内で他のウィジェットを作成およびレンダリングすることもできます。たとえば、 buf でメソッドを直接呼び出す代わりに、ウィジェットは Span のベクトルを持つ Line ウィジェットを作成できます。ここで、名前の Span この Line ウィジェットは、ウィジェットの render メソッド内でレンダリングできます。

ネストされたウィジェットを使用した同じ挨拶の例です。

struct GreetingWidget {
name: String,
}
impl Widget for GreetingWidget {
fn render(self, area: Rect, buf: &mut Buffer) {
let hello = Span::raw("Hello, ");
let name = Span::styled(self.name, Modifier::BOLD);
let line = Line::from(vec![hello, name]);
line.render(area, buf);
}
}

このアプローチにより、ウィジェットを作成して再利用できます。たとえば、 Line ウィジェットは、他のウィジェットやアプリケーションの他の部分でも使用できます。さらに、レンダリングに関連するコードが一貫した場所 ( impl Widget ブロック) で編成されるため、ウィジェットのテストとメンテナンスを容易にすることができます。

ステートフルウィジェットの実装

状況によっては、ウィジェットが自分自身をレンダリングしながら余分な状態を変異させることができる必要がある場合があります。この例は、内蔵 List ウィジェットがどのように機能するかです。レンダリング中、 List は状態内のスクロール位置を更新して、選択したアイテムがレンダリングエリアに表示されるようにします。

フレームカウントウィジェットの StatefulWidget trait を実装する例は次のとおりです。

struct FrameCountWidget {
style: Style,
}
impl StatefulWidget for FrameCountWidget {
type State = i32;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut i32) {
*state += 1;
let text = format!("Frame count: {state}");
Line::styled(text, self.style).render(area, buf);
}
}

この例では、 FrameCount ウィジェットがレンダリングされるたびに状態を増やし、フレーム数をカウントします。

WidgetRefの実装

Ratatui 0.26.0では、[WidgetRef] (および同様に[StatefulWidgetRef]) trait を追加しました。これらにより、参照によってレンダリングされるウィジェットを作成できます。これは、すべてのフレームで構築する代わりに複数回レンダリングできるウィジェットを保存するのに役立ちます。また、 Box<dyn T> を使用してウィジェットをボクシングすることにより、ウィジェットの動的コレクション (レイアウトのペインなど) を簡単に作成できます。

WidgetRef / StatefulWidgetRef の実装は、trait の消費バージョンの実装に似ています (違いは、メソッド名が render_ref であり、自己は参照であるということです) 。

struct GreetingWidget {
name: String,
}
impl WidgetRef for GreetingWidget {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
let hello = Span::raw("Hello, ");
let name = Span::styled(self.name, Modifier::BOLD);
let line = Line::from(vec![hello, name]);
line.render(area, buf);
}
}

これは、フレーム間にウィジェットを保存する方法として役立ちます。例えば。:

struct App {
greeting: GreetingWidget,
}
// and then later:
frame.render_widget_ref(&app.greeting, area);

さまざまなタイプのウィジェットのコレクション、またはコンパイル時間に既知のタイプを持たない単一のウィジェットがある状況では、REFのtrait により、[Box<T>]を使用してウィジェットをtrait オブジェクトとして保存することができます。

例えば。次のコードは、 Vec に2つの異なるウィジェットが保存されている方法を示しています。

struct Greeting { ... }
struct Farewell { ... }
impl WidgetRef for Greeting { ... }
impl WidgetRef for Farewell { ... }
let widgets: Vec<Box<dyn WidgetRef>> = vec![
Box::new(Greeting { name: "alice".into() }),
Box::new(Farewell { name: "bob".into() })
];
for widget in widgets {
widget.render_ref(area, buf);
}

[Widget]: https://docs.rs/ratatui/latest/ratatui/widgets/trait .Widget.html [StatefulWidget]: https://docs.rs/ratatui/latest/ratatui/widgets/trait .StatefulWidget.html [WidgetRef]: https://docs.rs/ratatui/latest/ratatui/widgets/trait .WidgetRef.html [StatefulWidgetRef]: https://docs.rs/ratatui/latest/ratatui/widgets/trait .StatefulWidgetRef.html Block: https://docs.rs/ratatui/latest/ratatui/widgets/block/struct.Block.html BarChart: https://docs.rs/ratatui/latest/ratatui/widgets/struct.BarChart.html Calendar: https://docs.rs/ratatui/latest/ratatui/widgets/calendar/struct.Monthly.html Canvas: https://docs.rs/ratatui/latest/ratatui/widgets/canvas/struct.Canvas.html Chart: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Chart.html Clear: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Clear.html Gauge: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Gauge.html LineGauge: https://docs.rs/ratatui/latest/ratatui/widgets/struct.LineGauge.html List: https://docs.rs/ratatui/latest/ratatui/widgets/struct.List.html Paragraph: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Paragraph.html Scrollbar: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Scrollbar.html Sparkline: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Sparkline.html Table: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Table.html Tabs: https://docs.rs/ratatui/latest/ratatui/widgets/struct.Tabs.html [String]: https://doc.rust-lang.org/std/string/struct.String.html [&str]: https://doc.rust-lang.org/std/primitive.str.html [Line]: https://docs.rs/ratatui/latest/ratatui/text/struct.Line.html [Span]: https://docs.rs/ratatui/latest/ratatui/text/struct.Span.html [Text]: https://docs.rs/ratatui/latest/ratatui/text/struct.Text.html [Box<T>]: https://doc.rust-lang.org/std/boxed/struct.Box.html [showcase]: https://ratatui.rs/showcase/widgets/ [third-party-widgets]: https://ratatui.rs/showcase/third-party-widgets/ [widgets-docs]: https://docs.rs/ratatui/latest/ratatui/widgets/index.html [Frame]: https://docs.rs/ratatui/latest/ratatui/struct.Frame.html [render_widget]: https://docs.rs/ratatui/latest/ratatui/struct.Frame.html#method.render_widget [render_stateful_widget]: https://docs.rs/ratatui/latest/ratatui/struct.Frame.html#method.render_stateful_widget [Awesome Ratatui]: https://github.com/ratatui/awesome-ratatui