rust 如何在ICED中更改背景

laik7k3q  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(182)

我只是对RUST语言和ICED crate感兴趣,坚持如何将图片设置为GUI背景。
我做了一个基本的登录GUI,如下所示:

现在我想把黑色背景改成这样的背景:

这是我的登录代码-我在这个项目中使用ICED:

pub fn main() -> Result<(), iced::Error> {
    let mut settings = Settings::default();
    settings.window.size = (400, 300);
    Login::run(settings)
}

struct Login {
    username: String,
    password: String,
    answer: String,
}
#[derive(Debug, Clone)]
enum Message
{
    Loginbutton,
    Username(String),
    Password(String),

}
impl Sandbox for Login {
    type Message = Message;

    fn new() -> Login {
        Login {
            username: String::new(),
            password: String::new(),
            answer: "".to_string(),
        }
    }

    fn title(&self) -> String {
        String::from("Login")
    }

    fn update(&mut self, message: self::Message)
    {
    match message
    {
        Message::Loginbutton => {},
        Message::Username(user_val) => self.username = user_val.parse().unwrap(),
        Message::Password(password_val) => self.password = password_val.parse().unwrap(),
    }
}

这里是我的布局,我设置主题为黑暗,现在我想改变黑暗的背景,一些图片:

fn view(&self) -> Element<Self::Message> {
    
        Column::new()
            .padding(20)
            .spacing(20)
            .push(Text::new("Username").style(color!(0xFB0000)))
            .push(TextInput::new("Enter your username",&self.username ).on_input(Message::Username))
            .push(Text::new("Password"))
            .push(TextInput::new("Enter your password",&self.password ).on_input(Message::Password))
            .push(Button::new(Text::new("Login".to_string())).on_press(Message::Loginbutton).style(iced::theme::Button::Secondary))
            .push(Text::new(&self.answer))
            .into()
    }
    fn theme(&self) -> iced::Theme {
        Theme::Dark        
    }
}
}
vwhgwdsa

vwhgwdsa1#

可悲的是,这不是很容易做到的时刻,因为它目前是不可能的,
1.使用Image作为Background(但是如果你只需要一个 Gradient 就足够了)
1.将小部件堆叠在彼此之上
然而,Overlay特性在原则上确实使这成为可能。
下面是如何实现以下布局的完整示例(基于OP和iced s' modal示例中的代码):

用于加载图像的文件夹结构:

.  iced_stackoverflow
├─ Cargo.lock
├─ Cargo.toml
├─ resources/
│  └─ ferris.png
├─ src/
│  └─ main.rs
└─ target/

Cargo.toml的特点:

[dependencies]
iced = { version = "0.10.0", features = ["advanced", "image"] }

main.rs中的代码:

use iced::{
    color,
    widget::{Button, Column, Container, Image, Text, TextInput},
    Element, Length, Sandbox, Settings, Theme,
};
use modal::Modal;

pub fn main() -> Result<(), iced::Error> {
    let mut settings = Settings::default();
    settings.window.size = (400, 300);
    Login::run(settings)
}

struct Login {
    username: String,
    password: String,
    answer: String,
}
#[derive(Debug, Clone)]
enum Message {
    Loginbutton,
    Username(String),
    Password(String),
}
impl Sandbox for Login {
    type Message = Message;

    fn new() -> Login {
        Login {
            username: String::new(),
            password: String::new(),
            answer: "".to_string(),
        }
    }

    fn title(&self) -> String {
        String::from("Login")
    }
    fn view(&self) -> Element<Self::Message> {
        let image = Image::new("resources/ferris.png")
            .width(Length::Fill)
            .height(Length::Fill);

        let background = Container::new(image)
            .width(Length::Fill)
            .height(Length::Fill)
            .center_x()
            .center_y();

        let login_form = Column::new()
            .padding(20)
            .spacing(20)
            .push(Text::new("Username").style(color!(0xFB0000)))
            .push(TextInput::new("Enter your username", &self.username).on_input(Message::Username))
            .push(Text::new("Password"))
            .push(TextInput::new("Enter your password", &self.password).on_input(Message::Password))
            .push(
                Button::new(Text::new("Login".to_string()))
                    .on_press(Message::Loginbutton)
                    .style(iced::theme::Button::Secondary),
            )
            .push(Text::new(&self.answer));

        Modal::new(background, login_form).into()
    }
    fn theme(&self) -> iced::Theme {
        Theme::Dark
    }

    fn update(&mut self, message: Self::Message) {
        match message {
            Message::Loginbutton => println!("{}", "Login button pressed."),
            Message::Username(text) => println!("Username text changed to {}.", text),
            Message::Password(text) => println!("Password text changed to {}.", text),
        }
    }
}

mod modal {
    use iced::advanced::layout::{self, Layout};
    use iced::advanced::overlay;
    use iced::advanced::renderer;
    use iced::advanced::widget::{self, Widget};
    use iced::advanced::{self, Clipboard, Shell};
    use iced::alignment::Alignment;
    use iced::event;
    use iced::mouse;
    use iced::{Color, Element, Event, Length, Point, Rectangle, Size};

    /// A widget that centers a modal element over some base element
    pub struct Modal<'a, Message, Renderer> {
        base: Element<'a, Message, Renderer>,
        modal: Element<'a, Message, Renderer>,
        on_blur: Option<Message>,
    }

    impl<'a, Message, Renderer> Modal<'a, Message, Renderer> {
        /// Returns a new [`Modal`]
        pub fn new(
            base: impl Into<Element<'a, Message, Renderer>>,
            modal: impl Into<Element<'a, Message, Renderer>>,
        ) -> Self {
            Self {
                base: base.into(),
                modal: modal.into(),
                on_blur: None,
            }
        }

        /// Sets the message that will be produces when the background
        /// of the [`Modal`] is pressed
        pub fn on_blur(self, on_blur: Message) -> Self {
            Self {
                on_blur: Some(on_blur),
                ..self
            }
        }
    }

    impl<'a, Message, Renderer> Widget<Message, Renderer> for Modal<'a, Message, Renderer>
    where
        Renderer: advanced::Renderer,
        Message: Clone,
    {
        fn children(&self) -> Vec<widget::Tree> {
            vec![
                widget::Tree::new(&self.base),
                widget::Tree::new(&self.modal),
            ]
        }

        fn diff(&self, tree: &mut widget::Tree) {
            tree.diff_children(&[&self.base, &self.modal]);
        }

        fn width(&self) -> Length {
            self.base.as_widget().width()
        }

        fn height(&self) -> Length {
            self.base.as_widget().height()
        }

        fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
            self.base.as_widget().layout(renderer, limits)
        }

        fn on_event(
            &mut self,
            state: &mut widget::Tree,
            event: Event,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
            renderer: &Renderer,
            clipboard: &mut dyn Clipboard,
            shell: &mut Shell<'_, Message>,
            viewport: &Rectangle,
        ) -> event::Status {
            self.base.as_widget_mut().on_event(
                &mut state.children[0],
                event,
                layout,
                cursor,
                renderer,
                clipboard,
                shell,
                viewport,
            )
        }

        fn draw(
            &self,
            state: &widget::Tree,
            renderer: &mut Renderer,
            theme: &<Renderer as advanced::Renderer>::Theme,
            style: &renderer::Style,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
            viewport: &Rectangle,
        ) {
            self.base.as_widget().draw(
                &state.children[0],
                renderer,
                theme,
                style,
                layout,
                cursor,
                viewport,
            );
        }

        fn overlay<'b>(
            &'b mut self,
            state: &'b mut widget::Tree,
            layout: Layout<'_>,
            _renderer: &Renderer,
        ) -> Option<overlay::Element<'b, Message, Renderer>> {
            Some(overlay::Element::new(
                layout.position(),
                Box::new(Overlay {
                    content: &mut self.modal,
                    tree: &mut state.children[1],
                    size: layout.bounds().size(),
                    on_blur: self.on_blur.clone(),
                }),
            ))
        }

        fn mouse_interaction(
            &self,
            state: &widget::Tree,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
            viewport: &Rectangle,
            renderer: &Renderer,
        ) -> mouse::Interaction {
            self.base.as_widget().mouse_interaction(
                &state.children[0],
                layout,
                cursor,
                viewport,
                renderer,
            )
        }

        fn operate(
            &self,
            state: &mut widget::Tree,
            layout: Layout<'_>,
            renderer: &Renderer,
            operation: &mut dyn widget::Operation<Message>,
        ) {
            self.base
                .as_widget()
                .operate(&mut state.children[0], layout, renderer, operation);
        }
    }

    struct Overlay<'a, 'b, Message, Renderer> {
        content: &'b mut Element<'a, Message, Renderer>,
        tree: &'b mut widget::Tree,
        size: Size,
        on_blur: Option<Message>,
    }

    impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
        for Overlay<'a, 'b, Message, Renderer>
    where
        Renderer: advanced::Renderer,
        Message: Clone,
    {
        fn layout(&self, renderer: &Renderer, _bounds: Size, position: Point) -> layout::Node {
            let limits = layout::Limits::new(Size::ZERO, self.size)
                .width(Length::Fill)
                .height(Length::Fill);

            let mut child = self.content.as_widget().layout(renderer, &limits);
            child.align(Alignment::Center, Alignment::Center, limits.max());

            let mut node = layout::Node::with_children(self.size, vec![child]);
            node.move_to(position);

            node
        }

        fn on_event(
            &mut self,
            event: Event,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
            renderer: &Renderer,
            clipboard: &mut dyn Clipboard,
            shell: &mut Shell<'_, Message>,
        ) -> event::Status {
            let content_bounds = layout.children().next().unwrap().bounds();

            if let Some(message) = self.on_blur.as_ref() {
                if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) = &event {
                    if !cursor.is_over(content_bounds) {
                        shell.publish(message.clone());
                        return event::Status::Captured;
                    }
                }
            }

            self.content.as_widget_mut().on_event(
                self.tree,
                event,
                layout.children().next().unwrap(),
                cursor,
                renderer,
                clipboard,
                shell,
                &layout.bounds(),
            )
        }

        fn draw(
            &self,
            renderer: &mut Renderer,
            theme: &Renderer::Theme,
            style: &renderer::Style,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
        ) {
            renderer.fill_quad(
                renderer::Quad {
                    bounds: layout.bounds(),
                    border_radius: Default::default(),
                    border_width: 0.0,
                    border_color: Color::TRANSPARENT,
                },
                Color {
                    a: 0.80,
                    ..Color::BLACK
                },
            );

            self.content.as_widget().draw(
                self.tree,
                renderer,
                theme,
                style,
                layout.children().next().unwrap(),
                cursor,
                &layout.bounds(),
            );
        }

        fn operate(
            &mut self,
            layout: Layout<'_>,
            renderer: &Renderer,
            operation: &mut dyn widget::Operation<Message>,
        ) {
            self.content.as_widget().operate(
                self.tree,
                layout.children().next().unwrap(),
                renderer,
                operation,
            );
        }

        fn mouse_interaction(
            &self,
            layout: Layout<'_>,
            cursor: mouse::Cursor,
            viewport: &Rectangle,
            renderer: &Renderer,
        ) -> mouse::Interaction {
            self.content.as_widget().mouse_interaction(
                self.tree,
                layout.children().next().unwrap(),
                cursor,
                viewport,
                renderer,
            )
        }

        fn overlay<'c>(
            &'c mut self,
            layout: Layout<'_>,
            renderer: &Renderer,
        ) -> Option<overlay::Element<'c, Message, Renderer>> {
            self.content.as_widget_mut().overlay(
                self.tree,
                layout.children().next().unwrap(),
                renderer,
            )
        }
    }

    impl<'a, Message, Renderer> From<Modal<'a, Message, Renderer>> for Element<'a, Message, Renderer>
    where
        Renderer: 'a + advanced::Renderer,
        Message: 'a + Clone,
    {
        fn from(modal: Modal<'a, Message, Renderer>) -> Self {
            Element::new(modal)
        }
    }
}

相关问题