Reputation: 648
I am pretty new to Rust. So I might be doing something dumb.
For context, I am using tui-rs to make a small terminal application. This is the relevant cleaned code.
use tui::widgets::{Block, List, Widget};
pub struct UI {
widgets: Vec<Box<dyn Widget>>,
}
let block = Block::default().title("Block").borders(Borders::ALL);
let list = List::new(items)
.block(Block::default().title("List").borders(Borders::ALL))
.style(Style::default().fg(Color::White))
.highlight_style(Style::default().add_modifier(Modifier::ITALIC))
.highlight_symbol(">>");
let widgets = vec![Box::new(block),Box::new(list)];
for i in 0..self.widgets.len() {
f.render_widget(self.widgets[i], self.chunks[i]);
}
...
Now you get the idea about what I am trying to achieve. But i keep getting this error on
f.render_widget(self.widgets[i], self.chunks[i])
;
the trait bound `std::boxed::Box<dyn tui::widgets::Widget>: tui::widgets::Widget` is not satisfied
the following other types implement trait `tui::widgets::Widget`:
tui::widgets::BarChart<'a>
tui::widgets::Block<'a>
tui::widgets::Chart<'a>
tui::widgets::Clear
tui::widgets::Gauge<'a>
tui::widgets::LineGauge<'a>
tui::widgets::List<'a>
tui::widgets::Paragraph<'a>
and 4 othersrustcE0277
terminal.rs(99, 12): required by a bound in `tui::Frame::<'a, B>::render_widget`
I have even tried the enum approach
struct Widgets{
List,
Box
}
pub struct UI {
widgets: Vec<Widgets>,
}
let widgets = vec![block,list];
Now the error is on let widgets = vec![block,list];
mismatched types
expected enum `ui::Widgets`, found struct `tui::widgets::List`
Upvotes: 1
Views: 171
Reputation: 604
The problem is not at the vec!
step but rather at the render_widget
step (for box way).
What is happening is that the trait Widget
is not implemented for Box<dyn Widget>
. It looks like the issue is at tui-rs end where they forgot to add a blanket impl for references.
You can try giving a reference like @maxim-gritsenko said: f.render_widget(&self.widgets[i], ...)
.
I am not sure that would work, though. If it does, its probably the best solution.
The enum solution can work, but you didn't actually make the enums correctly.
What you need is something like:
enum MyWidgets {
List(tui::widgets::List),
Block(tui::widgets::Block),
}
let widgets = vec![MyWidgets::List(list), MyWidgets::Block(block)];
for widget in widgets {
match widget {
MyWidget::List(list) => f.render_widget(list, ...),
MyWidget::Block(block) => f.render_widget(block, ...),
}
}
Upvotes: 3