Rust终端UI组件库tui-tree-widget的使用,打造高效可交互的树形结构终端界面
Rust终端UI组件库tui-tree-widget的使用,打造高效可交互的树形结构终端界面
Ratatui Tree Widget
一个用于显示树形数据结构的Ratatui Widget组件。
最初是为mqttui
项目开发的专用组件。
安装
在项目目录中运行以下Cargo命令:
cargo add tui-tree-widget
或者在Cargo.toml中添加以下行:
tui-tree-widget = "0.23.1"
完整示例代码
下面是一个使用tui-tree-widget创建交互式树形结构的完整示例:
use ratatui::{
backend::TestBackend,
buffer::Buffer,
layout::Rect,
style::{Color, Modifier, Style},
symbols,
text::{Line, Span},
widgets::{Block, Borders},
Terminal,
};
use tui_tree_widget::{Tree, TreeItem};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建终端后端
let backend = TestBackend::new(30, 10);
let mut terminal = Terminal::new(backend)?;
// 构建树形数据
let items = vec![
// 第一级节点
TreeItem::new_leaf("Item 1"),
// 可展开的第二级节点
TreeItem::new(
"Item 2",
vec![
TreeItem::new_leaf("Child 1"),
TreeItem::new_leaf("Child 2"),
TreeItem::new(
"Child 3",
vec![
TreeItem::new_leaf("Grandchild 1"),
TreeItem::new_leaf("Grandchild 2"),
],
)
.expect("All item identifiers must be unique"),
],
)
.expect("All item identifiers must be unique"),
TreeItem::new_leaf("Item 3"),
];
// 创建树形Widget
let tree = Tree::new(items)
.block(
Block::default()
.title("Tree")
.borders(Borders::ALL)
)
.highlight_style(
Style::default()
.fg(Color::Black)
.bg(Color::LightGreen)
.add_modifier(Modifier::BOLD),
)
.highlight_symbol(">>");
// 渲染树形结构
terminal.draw(|f| {
let size = f.size();
f.render_widget(tree, size);
})?;
Ok(())
}
代码说明
-
后端设置:使用
TestBackend
创建终端环境,实际应用中可以使用CrosstermBackend
或TermionBackend
。 -
树形数据构建:
TreeItem::new_leaf()
创建叶子节点TreeItem::new()
创建可展开的父节点,包含子节点列表
-
树形Widget配置:
block()
添加边框和标题highlight_style()
设置选中项样式highlight_symbol()
设置选中项前缀符号
-
渲染:通过
terminal.draw()
将树形Widget渲染到终端
交互控制
实际应用中,可以通过键盘事件来控制树形结构的展开/折叠和选择:
match key_event.code {
KeyCode::Up => tree_state.key_up(),
KeyCode::Down => tree_state.key_down(),
KeyCode::Left => tree_state.key_left(),
KeyCode::Right => tree_state.key_right(),
KeyCode::Enter => {
if let Some(item) = tree_state.selected() {
println!("Selected: {}", item);
}
}
_ => {}
}
更多信息
这个组件非常适合需要展示层级数据的命令行工具,如文件浏览器、配置查看器等,能有效提升用户体验。
1 回复
Rust终端UI组件库tui-tree-widget的使用指南
tui-tree-widget
是一个用于在终端中创建交互式树形结构的Rust组件库,基于流行的tui-rs
终端用户界面库构建。
功能特点
- 支持可折叠/展开的树形节点
- 键盘导航(上下箭头、左右箭头)
- 自定义节点渲染
- 支持异步加载节点
- 与
crossterm
或termion
后端兼容
基本使用方法
添加依赖
首先在Cargo.toml
中添加依赖:
[dependencies]
tui = "0.19"
tui-tree-widget = "0.7"
crossterm = "0.26" # 或其他你喜欢的后端
基本示例
use tui::{
backend::Backend,
widgets::{Block, Borders},
Terminal,
};
use tui_tree_widget::{Tree, TreeItem};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化终端
let mut terminal = setup_terminal()?;
// 创建树形数据
let items = vec![
TreeItem::new_leaf("a", "Leaf A"),
TreeItem::new(
"b",
"Parent B",
vec![
TreeItem::new_leaf("b-1", "Child B-1"),
TreeItem::new_leaf("b-2", "Child B-2"),
],
)?,
TreeItem::new_leaf("c", "Leaf C"),
];
// 创建树形组件
let tree = Tree::new(items)
.block(Block::default().title("Tree").borders(Borders::ALL));
// 主循环
loop {
terminal.draw(|f| {
let area = f.size();
f.render_widget(tree.clone(), area);
})?;
// 处理输入事件...
}
// 恢复终端
restore_terminal(&mut terminal)?;
Ok(())
}
高级用法
自定义节点渲染
use tui::style::{Style, Color};
let tree = Tree::new(items)
.block(Block::default().title("Tree").borders(Borders::ALL))
.highlight_style(Style::default().fg(Color::Yellow))
.unwrap();
处理交互事件
use crossterm::event::{self, Event, KeyCode};
match event::read()? {
Event::Key(key) => match key.code {
KeyCode::Up => tree.prev(),
KeyCode::Down => tree.next(),
KeyCode::Left => tree.close(),
KeyCode::Right => tree.open(),
KeyCode::Enter => {
if let Some(selected) = tree.selected() {
println!("Selected: {}", selected);
}
}
_ => {}
},
_ => {}
}
异步加载节点
use std::sync::{Arc, Mutex};
let items = Arc::new(Mutex::new(vec![
TreeItem::new("async", "Load More", vec![])?,
]));
// 在事件处理中
if let Some(selected) = tree.selected() {
if selected == "async" {
let mut items = items.lock().unwrap();
*items = vec![
TreeItem::new_leaf("loaded-1", "Loaded Item 1"),
TreeItem::new_leaf("loaded-2", "Loaded Item 2"),
];
tree.set_items items.clone());
}
}
实用技巧
- 性能优化:对于大型树结构,考虑使用延迟加载技术
- 自定义样式:可以自定义不同层级节点的缩进和样式
- 集成到现有应用:可以很容易地与其他
tui-rs
组件结合使用
完整示例
use tui::{
backend::CrosstermBackend,
Terminal,
widgets::{Block, Borders},
layout::Rect,
};
use tui_tree_widget::{Tree, TreeItem};
use crossterm::{
event::{self, Event, KeyCode},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::{io, sync::{Arc, Mutex}};
fn main() -> io::Result<()> {
// 设置终端
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
// 创建树形数据
let items = Arc::new(Mutex::new(vec![
TreeItem::new_leaf("file1", "Document.txt"),
TreeItem::new(
"dir1",
"Projects",
vec![
TreeItem::new_leaf("proj1", "Project A"),
TreeItem::new_leaf("proj2", "Project B"),
],
)?,
TreeItem::new_leaf("file2", "Notes.md"),
]));
let mut tree = Tree::new(items.lock().unwrap().clone())
.block(Block::default().title("File Explorer").borders(Borders::ALL));
// 主循环
loop {
terminal.draw(|f| {
let size = f.size();
f.render_widget(tree.clone(), size);
})?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => break,
KeyCode::Up => tree.prev(),
KeyCode::Down => tree.next(),
KeyCode::Left => tree.close(),
KeyCode::Right => tree.open(),
KeyCode::Enter => {
if let Some(selected) = tree.selected() {
println!("Selected: {}", selected);
}
}
_ => {}
}
}
}
// 恢复终端
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok(())
}
tui-tree-widget
为终端应用提供了强大的树形结构展示能力,结合Rust的性能优势,可以构建出既美观又高效的终端用户界面。