Popups (overwrite regions)
Ratatui は、アプリケーションがバッファに書き込む順序でテキストをレンダリングします。つまり、前の命令は後の命令によって上書きされます。ただし、ウィジェットはレンダリング先の領域内のすべてのセルを常にクリアするわけではないことに注意してください。これにより、以前にバッファにレンダリングされたシンボルとスタイルが、それらのセルの上にレンダリングされたセルに「にじみ出る」可能性があります。
次のコードはこの問題を示しています。
use lipsum::lipsum;use ratatui::{ backend::CrosstermBackend, crossterm::{ event::{self, Event}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }, layout::Rect, style::{Style, Stylize}, widgets::{Block, Borders, Paragraph, Wrap}, Frame, Terminal,};
// -- snip --
fn ui(frame: &mut Frame) { let area = frame.area(); let background_text = Paragraph::new(lipsum(1000)) .wrap(Wrap { trim: true }) .light_blue() .italic() .on_black(); frame.render_widget(background_text, area);
// take up a third of the screen vertically and half horizontally let popup_area = Rect { x: area.width / 4, y: area.height / 3, width: area.width / 2, height: area.height / 3, }; let bad_popup = Paragraph::new("Hello world!") .wrap(Wrap { trim: true }) .style(Style::new().yellow()) .block( Block::new() .title("Without Clear") .title_style(Style::new().white().bold()) .borders(Borders::ALL) .border_style(Style::new().red()), ); frame.render_widget(bad_popup, popup_area);}
背景色 (この場合は黒) 、イタリック体、およびロレムのipsumの背景テキストがポップアップを介して表示されることに注意してください。
この問題は、メインポップアップをレンダリングする前にClear
ウィジェットをレンダリングすることにより、簡単に防ぐことができます。この手法を使用して Popup
ウィジェットを作成する方法の例を次に示します。
use derive_setters::Setters;use lipsum::lipsum;use ratatui::{ backend::CrosstermBackend, buffer::Buffer, crossterm::{ event::{self, Event}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, }, layout::Rect, style::{Style, Stylize}, text::{Line, Text}, widgets::{Block, Borders, Clear, Paragraph, Widget, Wrap}, Frame, Terminal,};
#[derive(Debug, Default, Setters)]struct Popup<'a> { #[setters(into)] title: Line<'a>, #[setters(into)] content: Text<'a>, border_style: Style, title_style: Style, style: Style,}
impl Widget for Popup<'_> { fn render(self, area: Rect, buf: &mut Buffer) { // ensure that all cells under the popup are cleared to avoid leaking content Clear.render(area, buf); let block = Block::new() .title(self.title) .title_style(self.title_style) .borders(Borders::ALL) .border_style(self.border_style); Paragraph::new(self.content) .wrap(Wrap { trim: true }) .style(self.style) .block(block) .render(area, buf); }}
次のコードで新しい Popup
ウィジェットを使用できます。
let popup = Popup::default() .content("Hello world!") .style(Style::new().yellow()) .title("With Clear") .title_style(Style::new().white().bold()) .border_style(Style::new().red()); frame.render_widget(popup, popup_area);
次の結果が得られます。
背景はデフォルトの背景に設定されており、背景テキストから斜体やシンボルがないことに注意してください。
この記事の完全なソースは、https://github.com/ratatui/ratatui-website/tree/main/code/how-to-overwrite-regions で入手できます