Open Kuraga13 opened 1 year ago
You can draw Widget inside Scrollable, drawing only rows inside a viewport. In my case freezes are gone(i've tested 10k rows).
Working example:
pub struct TableContents<Message> {
item_height:f32,
contents:Vec<Vec<String>>,
on_double_clicked: Box<dyn Fn() -> Message>,
}
impl <Message>TableContents<Message> {
pub fn new(item_height:f32,
contents:Vec<Vec<String>>,
on_double_clicked:impl Fn() -> Message + 'static
) -> Self {
Self {item_height,contents,on_double_clicked:Box::new(on_double_clicked)}
}
}
pub fn table_contents< Message>(item_height:f32,
contents:Vec<Vec<String>>,
on_double_clicked:impl Fn() -> Message + 'static) -> TableContents<Message> {
TableContents::new(item_height,contents,on_double_clicked)
}
impl<Message:std::clone::Clone> Widget<Message, iced::Renderer> for TableContents<Message>
{
fn width(&self) -> Length {
Length::Fill
}
fn height(&self) -> Length {
Length::Fill
}
fn on_event(
&mut self,
_state: &mut Tree,
event: iced::Event,
layout: Layout<'_>,
cursor_position: Point,
_renderer: &iced::Renderer,
_clipboard: &mut dyn Clipboard,
_shell: &mut Shell<'_, Message>) -> Status {
Status::Ignored
}
fn draw(
& self,
_state: &widget::Tree,
renderer: &mut iced::Renderer,
_theme: &iced::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
viewport: &Rectangle,
) {
use iced_native::text::Renderer as text_renderer;
let mut viewport_layout_y=(viewport.y-layout.bounds().y);
let mut end_y=viewport.y+viewport.height;
let mut number_of_element=(viewport_layout_y/self.item_height) as i32;
let mut element_bounds=Rectangle{x:layout.bounds().x, y:(self.item_height*number_of_element as f32)+layout.bounds().y, width:layout.bounds().width, height:self.item_height};
let mut contents=self.contents.clone();
while element_bounds.y<end_y{
let mut rectangle_bounds=element_bounds;
if element_bounds.y+element_bounds.height>end_y {
rectangle_bounds.height=end_y-element_bounds.y;
}
renderer.fill_quad(
renderer::Quad {
bounds: rectangle_bounds,
border_radius: Default::default(),
border_width: 0.0,
border_color: Color::WHITE,
}, Background::Color(if number_of_element % 2 == 0 { COLOR_LIGHTER } else { COLOR_DARKER })
);
let mut text_bounds=element_bounds;
text_bounds.y=element_bounds.center_y();
if let Some(itemvec)=contents.get(number_of_element as usize) {
if itemvec.len()==1{
text_bounds.x=element_bounds.center_x();
renderer.fill_text(
iced_native::text::Text {
content: itemvec[0].as_str(),
bounds: text_bounds,
size: 20.0,
color: Color::WHITE,
font: Font::Default,
horizontal_alignment: Horizontal::Center,
vertical_alignment: Vertical::Center,
}
);
}else{
text_bounds.width/=itemvec.len() as f32;
for item in itemvec.iter(){;
renderer.fill_text(
iced_native::text::Text {
content: format!(" {}",item.as_str()).as_str(),
bounds: text_bounds,
size: 20.0,
color: Color::WHITE,
font: Font::Default,
horizontal_alignment: Horizontal::Left,
vertical_alignment: Vertical::Center,
}
);
text_bounds.x+=text_bounds.width;
}
}
}
element_bounds.y+=element_bounds.height;
number_of_element+=1;
}
}
fn layout(&self, renderer: &iced::Renderer, limits: &Limits) -> Node {
layout::Node::new(Size{
width: limits.max().width,
height: self.item_height*((self.contents.len()) as f32)
})
}
}
impl<'a, Message> From<TableContents<Message>> for Element< 'a,Message, iced::Renderer>
where Message:'a,
Message:std::clone::Clone
{
fn from(table_contents: TableContents<Message>) -> Self {
Self::new(table_contents)
}
}
Sry if this code is bad, im new in rust. But it works without any freezes. One question to maintainers: how can i calculate item_height inside this widget, if i wanna draw only 7 rows in one view? Only way that i see requires viewport data inside layout method.
Hi, thanks a lot for your answer! If it works, it'll be awesome! I tried to build your code, what version of iced are you using? I am quite a beginner in iced. While the compiler does not seem to see any crate.
impl<Message:std::clone::Clone> Widget<Message, iced::Renderer> for TableContents<Message>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `iced_native::Renderer` is not implemented for `iced_graphics::renderer::Renderer<iced_wgpu::backend::Backend, iced::Theme>`
My Cargo.toml:
iced={version="0.8.0",features=["default_system_font","image","debug"]}
iced_lazy= "0.5.0"
iced_native="0.9.1"
iced_graphics = "0.7.0"
iced_futures = "0.6.0"
Works! I had an old version of iced, 0.7. Thanks, I struggled with this for a long time, great, zbs.
Hey, I had the same issue in my app, so I created this small library to fix it! Although this component isn't finished, it's still usable. iced-flatlist
Hey, I had the same issue in my app, so I created this small library to fix it! Although this component isn't finished, it's still usable. iced-flatlist
This is great! Will have to try. I did something too HexBufferWidget
I'll try to bump the version of my component, it uses an older version of iced. When I click your link it goes nowhere, maybe it is set to be private?
Ok I will wait. Link corrected
Alright, bumped iced version to 0.8.0
Is there an existing issue for this?
Is this issue related to iced?
What happened?
I'm trying to make something like a Hex Viewer, apparently, this only works with a small number of lines, since the window just freezes. Is there any way to make a table? Originally used the iced_aw widget grid so I asked them first. It was explained to me that this is some kind of problem inside iced, I tried the following code right in the tour example:
What is the expected behavior?
The text table is a must have for any gui. Tables contain the logic of a very large number of applications. I would like to know if this can be fixed and how
Version
master
Operative System
Windows
Do you have any log output?
No response