Iced widget::rule::horizontal - unable to apply a style

I have a function that returns an iced element to be used as a view. It works fine with one exception. I want a thin black line, via a horizontal rule, but am unable to figure out how to apply a style. The error message is "closure is expected to take 1 argument but it takes 2". In the code I have a working version, not styled i.e. not black, and a commented out section where I have attempted unsuccessfully to apply a style. Any input will be appreciated.

pub fn get_update_db_view(rec_read: u64, rec_inserted: u64) -> iced::Element<'static, Message> {

    let column_widget = widget::column![

        widget::Container::new(
            widget::Button::new(widget::text("Home").size(15.0))
                .on_press(Message::GoToHomeScreen)
                .style(|_, _| widget::button::Style {
                    background: None,
                    text_color: color!(0x0000FF).into(),
                    border: Border {
                        color: color!(0x000000).into(),
                        width: 0.0,
                        radius: iced::border::Radius::new(0.0),
                    },
                    ..Default::default()
                }) 
        )
        .height(Length::FillPortion(1))
        .width(Length::Fill)
        .align_x(iced::alignment::Horizontal::Right)
        .align_y(iced::alignment::Vertical::Top),

        widget::Container::new(widget::text("Update Database").size(30.0))
            .height(Length::FillPortion(1))
            .width(Length::Fill)
            .align_x(iced::alignment::Horizontal::Center)
            .align_y(iced::alignment::Vertical::Center),

        widget::Container::new(widget::rule::horizontal(1))
            .width(Length::Fill)
            .height(Length::FillPortion(1)),    

//         widget::Container::new(
//             widget::rule::horizontal(1)
// // closure is expected to take one argument by it takes two
//                 .style(|_, _| widget::rule::Style {
//                     color: color!(0x0000FF).into(),
//                     radius: iced::border::Radius::new(0.0),
//                     fill_mode: widget::rule::FillMode::Full,
//                     snap: false,
//                     },
//                 ) // end of rule style
//         ) // end of container
//         .width(Length::Fill)
//         .height(Length::FillPortion(1)),

        widget::Container::new(
            widget::row![
                widget::column![
                    widget::Container::new(widget::text("Records Read:").size(20.0))
                        .width(Length::Fill)
                        .align_x(Horizontal::Right),
                    widget::Container::new(
                        widget::text("Records Inserted:").size(20.0)
                    )
                    .width(Length::Fill)
                    .align_x(Horizontal::Right),
                ]
                .width(Length::FillPortion(1))
                .spacing(15),
                widget::column![
                    widget::Container::new(
                        widget::text(rec_read.to_string()).size(20.0)
                    )
                    .padding(iced::padding::left(10)),
                    widget::Container::new(
                        widget::text(rec_inserted.to_string()).size(20.0)
                    )
                    .padding(iced::padding::left(10)),
                ]
                .width(Length::FillPortion(1))
                .spacing(15),
            ]
            .width(Length::Fill) // .spacing(20) // width of row
        )
        .height(Length::FillPortion(2))
        .padding(iced::padding::bottom(30))
        .align_y(iced::alignment::Vertical::Center), // height of container

        widget::Container::new(
            widget::row![
                widget::Container::new(
                    widget::Button::new(
                        widget::text("Update").size(25.0)
                    )
                    .on_press(Message::UpdateDataBase)
                    .style(|_, _| widget::button::Style {
                        background: None,
                        text_color: color!(0x0000FF).into(),
                        border: Border {
                            color: color!(0x000000).into(),
                            width: 0.0,
                            radius: iced::border::Radius::new(0.0),
                        }, // end of border style  
                        ..Default::default()
                        } // end of widget::button::style
                    ) // end of button widget
                ), // end of inner container
            ] // end of row
        ) // end of outer container

        .height(Length::FillPortion(3))
        .width(Length::Fill)
        .padding(iced::padding::bottom(80))
        .align_x(iced::alignment::Horizontal::Center)
        .align_y(iced::alignment::Vertical::Center),


    ]; // end of column

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

    my_container.into()

}

StyleFn for Rule only takes one argument.

Change:

// .style(|_, _| widget::rule::Style {

To:

// .style(|_| widget::rule::Style {

But I note that the actual doc comment appears to be incorrect, stating that the closure takes both a Theme and a Status, which is true of some widgets, like Button, but not Rule.

A couple of other notes:

  • remember Length::FillPortion(1) is the same as Length::Fill
  • idiomatic iced code prefers to use the helper widget construction functions, e.g. widget::button(...), rather than widget::Button::new(...)

Thank you. The style now works. I have two follow up questions.

  1. I have changed my button call outs to use the helper widget construction function. Should I do the same thing for containers (currently using widget::Container::new)?
  2. Regarding Length::FillPortion(1), if my view has two containers in a column and I give each one a height with a FillPortion of 1, doesn't each container get 50% of the window height or am I misunderstanding how it works?
  1. Yes, always let the functional constructors over new (but I'll say again that this just applies to iced, not necessarily rust more more generally.)

  2. Lengths get resolved to a "fill factor", here. I slightly lost track of your rows and columns, but it looked to me like at least some of your FillPortion(1)s are superfluous. You're right about how the space gets evenly distributed in your 2-column example.

Now that you are using the functional constructors, you can lean into the numerous helper functions e.g. I'm pretty sure you can replace at least two of your Container::new with a center and a right.

1 Like