Rust + Iced: How do I place a border around a grid widget

I have a function that creates a view. In the view I display data in a grid. It works but I am unable to figure out how to place a border around each grid element so it looks like a spreadsheet. I would try another widget if required. Any assistance will be appreciated. Below is the function.

pub fn closing_view<'a>(heading: &str, query_results: &'a Vec<QueryResults>) -> iced::Element<'a, Message> {

    let mut grid_height = 0.0; 
    let mut my_grid = Grid::new();

    my_grid = my_grid
        .columns(2)
        .spacing(15)  // want 25 horizontal 0 vertical spacing between cells, default = 0
        .width(260) 
        ;

    for result in query_results {

        let naive_date = NaiveDate::parse_from_str(&result.date, "%Y-%m-%d").unwrap();
        let formatted_date = naive_date.format("%b %e, %Y").to_string();

        my_grid = my_grid
            .push(widget::text(format!("{}", formatted_date)).size(20.0).align_x(Horizontal::Right))
            .push(widget::text(format!("${:.2}", result.close)).size(20.0).align_x(Horizontal::Left));
        grid_height += 38.0
        
    }

    my_grid = my_grid.height(Length::Fixed(grid_height));

    let column_widget = 

        widget::column![
    
            widget::container(
                widget::button(widget::text("Home").size(15.0))
                    .on_press(Message::GoToHomeScreen)
                    .style(btn_blue_no_border)
            )
                .width(Length::Fill)
                .align_x(Horizontal::Right)
                .align_y(Vertical::Top),


            widget::container(
                widget::text(format!("{}", heading)).size(30.0)
            )
            .width(Length::Fill)
            .padding(iced::padding::bottom(10))
            .align_x(Horizontal::Center)
            .align_y(Vertical::Center), 

            widget::container(
                widget::row![
                    widget::text("Date").size(20.0),
                    widget::text("Close").size(20.0),
                ]
                .width(Length::Fill)
                .spacing(65)
                .padding(iced::padding::top(20))
                .padding(iced::padding::left(210))
            )
            .width(Length::Fill)
            .align_x(Horizontal::Center), 

            widget::rule::horizontal(1)
                .style(horizontal_rule),
        
            widget::scrollable(
                widget::container(
                    my_grid
                ) // end of container
                .padding(iced::padding::top(9))
                .width(Length::Fill)
                .align_x(Horizontal::Center)
                .align_y(Vertical::Top)
            ) // end of scrollable
        ];

    let my_container: widget::Container<'_, Message> =
        widget::Container::new(column_widget)
            .width(Length::Fill)
            .height(Length::Fill)
            .style(container_style);

    my_container.into()

}

Can't you pass a custom style with the borders like this?

widget::container(
                    my_grid
                ) // end of container
                .padding(iced::padding::top(9))
                .width(Length::Fill)
                .align_x(Horizontal::Center)
                .align_y(Vertical::Top)
                .style(Style::default().border(...))

I tried applying a style to the container with the fn below. It puts a border around the edges of the container not the individual elements in the grid.

.style(container_style_grid)    // added to container

pub fn container_style_grid(_theme: &Theme) -> widget::container::Style {

    let blue = color!(0x0000FF);
    let black = color!(0x000000);
    let sky_blue = color!(0x87ceeb);

    widget::container::Style {
        text_color: Some((black).into()),
        background: None,
        border: Border {
            color: (black).into(),
            width: 2.0.into(),
            radius: Radius::new(5.0),
        },
        ..widget::container::Style::default()
    }
}

After considerable research I could not determine how to put a border around the elements in a gird widget. So I used the container, column, row and text widgets to achieve a spreadsheet like look. I use container widgets to place borders around each text widget. Works. See code below.

pub fn testing_view<'a>(heading: &str, query_results: &'a Vec<QueryResults>) -> iced::Element<'a, Message> {

    let mut col1: widget::Column<'_,Message, Theme, Renderer> = widget::Column::new();
    let mut col2: widget::Column<'_,Message, Theme, Renderer> = widget::Column::new();  
    
    let cell_width = 150.0; 
    let cell_height = 30.0;

    for result in query_results {

        let naive_date = NaiveDate::parse_from_str(&result.date, "%Y-%m-%d").unwrap();
        let formatted_date = naive_date.format("%b %e, %Y").to_string();

        col1 = col1.push(widget::container(
            widget::text(format!("{}", formatted_date))
                    .size(20.0)
            )
            .width(Length::Fixed(cell_width))
            .height(Length::Fixed(cell_height))
            .align_x(Horizontal::Center)
            .align_y(Vertical::Center)
            .style(container_style_spreadsheet)
        );

        col2 = col2.push(widget::container(
            widget::text(format!("${:.2}", result.close))
                    .size(20.0)
            )
            .width(Length::Fixed(cell_width))
            .height(Length::Fixed(cell_height))
            .align_x(Horizontal::Center)
            .align_y(Vertical::Center)
            .style(container_style_spreadsheet)
        );

    }

    let column_widget = 

        widget::column![
    
            widget::container(
                widget::button(widget::text("Home").size(15.0))
                    .on_press(Message::GoToHomeScreen)
                    .style(btn_blue_no_border)
            )
                .width(Length::Fill)
                .align_x(Horizontal::Right)
                .align_y(Vertical::Top),


            widget::container(
                widget::text(format!("{}", heading)).size(30.0)
            )
            .width(Length::Fill)
            .padding(iced::padding::bottom(10))
            .align_x(Horizontal::Center)
            .align_y(Vertical::Center), 

            widget::container(
                widget::row![
                    widget::text("Date").size(20.0),
                    widget::text("Close").size(20.0),
                ]
                .width(Length::Fill)
                .spacing(110)
                .padding(iced::padding::top(20))
                .padding(iced::padding::left(200))
            )
            .width(Length::Fill)
            .align_x(Horizontal::Center), 

            widget::container(
                widget::rule::horizontal(1)
                    .style(horizontal_rule)
            )
            .width(Length::Fill)
            .padding(iced::padding::bottom(5)),
        
            widget::scrollable(
                widget::container(
                    widget::row![

                        col1
                        .align_x(Horizontal::Right)
                        .width(Length::FillPortion(1)),

                        col2
                        .align_x(Horizontal::Left)
                        .width(Length::FillPortion(1)),

                    ] // end of row

                ) // end of container
                .padding(iced::padding::bottom(15))
                .width(Length::Fill)
                .align_x(Horizontal::Center)
                .align_y(Vertical::Top)
                .style(container_style_grid)    
            )
            , // end of scrollable

        ];

    let my_container: widget::Container<'_, Message> =
        widget::Container::new(column_widget)
            .width(Length::Fill)
            .height(Length::Fill)
            .style(container_style);

    my_container.into()

}

1 Like