[Aprenda Rust juntos | Framework | framework iced] framework GUI multiplataforma nativo de ferrugem - iced


prefácio

Para aprender uma linguagem de programação, você nunca deve abandonar a aplicação da linguagem de programação. Ao aprender outras linguagens de programação, como C++, é muito chato aprender apenas gramática, estrutura de dados e algoritmo, isso é uma questão de perseverança. A melhor maneira neste momento é tornar o aprendizado interessante. Quando eu estava estudando, a fonte do meu interesse era fazer lindas janelas no Windows para melhorar meu aprendizado e eficiência no trabalho. Por isso, estudei QT, MFC, esses frameworks são muito bons e de fato alcançaram o efeito que desejo, mas o desenvolvimento é mais complicado. Mais tarde, aprendi qt python e o desenvolvimento ficou muito conveniente, mas um novo problema apareceu novamente, ou seja, a embalagem não é conveniente, para por isso, experimentei tortuosas explorações nesta estrada. Neste momento, aprender Rust é o mesmo. Se você deseja melhorar sua capacidade de aprendizado, deve encontrar os pontos de interesse. Para Rust, eu realmente quero usar as vantagens do Rust para criar janelas do Windows e também encontrei soluções, como o qt do Rust, mas é complicado, serão apresentadas em um artigo posterior; há também o Tauri UI, um framework de interface do usuário multiplataforma que usa Rust como back-end, sua ideia é mais como Electron, o front-end usa layout html+css e, em seguida, o back-end usa Rust e, em seguida, empacota o aplicativo. O método de uso será apresentado posteriormente nesta série de artigos; há também o Iced, que é apresentado neste artigo, que é mais parecido com a vibração do Rust , uma estrutura GUI multiplataforma baseada em Elm.

Iced é um framework GUI no qual estou mais interessado. Seu método de desenvolvimento é bastante amigável para pessoas como eu que aprenderam Vue, e é muito confortável com as características do Rust. Além disso, sua aparência também é bastante alta, por isso aprendo.

Características do Gelado

  • Simples e fácil de usar, com uma série de APIs integradas
  • Type-safe, com um modelo de programação interativo
  • Plataforma cruzada (suporta Windows, Mac, Linux e Web)
  • layout responsivo
  • baseado em widgets
  • Suporta widgets personalizados
  • Existem outros recursos, é recomendável ir ao Github para visualizar

1. Crie o projeto

1. Crie um projeto normalmente

Primeiro crie um projeto

cargo new gui_iced_001

2. Ideia de importação

Importar projeto usando ideia

3. Introduzir dependências

Abra Cargo.toml e escreva nas dependências

iced = "0.4"

注意:Estou usando uma versão posterior a 2021. Caso não esteja, é recomendável acessar o site oficial para conhecer a estratégia de processamento correspondente, que não será explicada aqui.

Neste ponto, o arquivo deve estar assim

Até agora, o projeto foi construído e o próximo passo é escrever nosso demo.

2. Escreva uma demonstração

Existem muitos exemplos de Iced no Github, entre os quais o mais clássico e o único exemplo escrito no site oficial é o Counter counter, porque a demonstração do Counter é realizada a partir daqui. Embora seja muito simples, há muitas armadilhas nele. Foi difícil escrever esta demonstração. Vamos falar sobre duas armadilhas. Este framework não faz distinção entre linhas e colunas. O código no exemplo é muito antigo. Eu dei o passo por passo. explorado.

O conteúdo a seguir será bem diferente do site oficial e o site oficial não funcionará, preste atenção à triagem.

1. Escreva o estado

Primeiro, escreva um State para o programa. Este conceito central inevitavelmente será usado ao aprender Vue, React ou Flutter. Não vou explicar aqui por enquanto, mas dar o código diretamente.

struct Counter {
    
    
    value: i32,
    // The local state of the two buttons
    increment_button: button::State,
    decrement_button: button::State,
}

Aqui está uma estrutura definida Counter , esta estrutura é considerada como o estado de nossa janela, seus membros valuerepresentam o valor da contagem do contador increment_buttone decrement_buttono estado dos dois botões + e -.

2. Defina o tipo de mensagem

O próximo passo é definir os tipos de mensagem usados ​​no programa. A interação no programa é realizada através de sinais. Qt faz isso muito bem. Se você estudou qt ou o front-end Vue e outros frameworks, isso é fácil de entender. .

#[derive(Debug, Clone, Copy)]
enum Message {
    
    
    IncrementPressed,
    DecrementPressed,
}

Duas mensagens são definidas aqui, uma é IncrementPressedpara representar o botão + foi clicado e a outra é para DecrementPressedrepresentar o botão - para ser clicado.

3. Escreva a lógica da visualização

O exemplo oficial aqui é implementar visualização e atualização diretamente para Counter, mas após minha exploração, não pode ser usado diretamente.

O programa Iced precisa implementar Application ou Sandbox. Não me importo com o que esses dois significam por enquanto. Usamos Sandbox aqui porque é bastante simples.

Um Sandbox vazio deve ficar assim

impl Sandbox for Counter {
    
    
    type Message = ();

    fn new() -> Self {
    
    
        todo!()
    }

    fn title(&self) -> String {
    
    
        todo!()
    }

    fn update(&mut self, message: Self::Message) {
    
    
        todo!()
    }

    fn view(&mut self) -> Element<'_, Self::Message> {
    
    
        todo!()
    }
}

Aqui está a introdução de cima para baixo

Mensagem

Representa todas as mensagens da janela atual. Ao usá-lo, você precisa passar a enumeração da mensagem definida. Por exemplo, o uso aqui deve ser assim,

#[derive(Debug, Clone, Copy)]
enum Message {
    
    
    IncrementPressed,
    DecrementPressed,
}
// ....
type Message = Message;

novo

Aqui é o mesmo que escrever código em geral, você precisa retornar sua própria instância, então não vou explicar muito

fn new() -> Self {
    
    
        Self {
    
     value: 0, increment_button: Default::default(), decrement_button: Default::default() }
    }

título

Veja o nome, aqui é para retornar o nome da janela atual

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

atualizar

Aqui está a lógica da mensagem da janela de processamento. Esta janela processa duas mensagens. Uma é que IncrementPressedo botão + foi clicado. Se for clicado, o valor do estado será +1. A outra é que DecrementPressedo botão - foi clicado. Se for clicado, o valor do estado é -1. O processamento aqui é bastante simples e não leva em consideração os valores de limite.

fn update(&mut self, message: Message) {
    
    
        match message {
    
    
            Message::IncrementPressed => {
    
    
                self.value += 1;
            }
            Message::DecrementPressed => {
    
    
                self.value -= 1;
            }
        }
    }

visualizar

Aqui para retornar o layout da janela, na verdade, para construir esta janela, aqui o código da janela do Counter é o seguinte

fn view(&mut self) -> Element<Message> {
    
    
        Column::new().push(
            Text::new("Counter")
        ).push(
            Row::new().push(
                Button::new(&mut self.increment_button, Text::new("+"))
                    .on_press(Message::IncrementPressed).width(Length::Fill),
            ).push(
                Text::new(self.value.to_string()).size(22),
            ).push(
                Button::new(&mut self.decrement_button, Text::new("-"))
                    .on_press(Message::DecrementPressed).width(Length::Fill),
            )
        )
        .align_items(Alignment::Center).into()
    }

Pode-se ver que a chamada de cadeia de tempo usada aqui é camada por camada. Seu código é muito semelhante ao flutter. Se você estudou flutter, deve estar muito familiarizado com ele. Aqui eu desenho uma imagem para explicar este código. Primeiro A janela é dividida em duas linhas por Coluna, e seu layout é consistente com a moldura vermelha, com duas linhas para cima e para baixo

注意:Neste quadro, linhas e colunas são estupidamente indistinguíveis.Coluna significa coluna, e neste quadro significa linha.

Na primeira linha, apenas um componente de texto é adicionado e o valor inicial é fornecido Counter. Originalmente, pretendia-se usar chinês aqui 计数器, mas essa coisa não oferece suporte a chinês.

Column::new().push(
            Text::new("Counter")
        )

Na segunda linha, adiciona-se um componente Row (componente) , e adiciona-se três componentes, que são dois Buttons, que são os botões + e -, e um componente Text para exibir o Value atual

//...
.push(
            Row::new().push(
                Button::new(&mut self.increment_button, Text::new("+"))
                    .on_press(Message::IncrementPressed).width(Length::Fill),
            ).push(
                Text::new(self.value.to_string()).size(22),
            ).push(
                Button::new(&mut self.decrement_button, Text::new("-"))
                    .on_press(Message::DecrementPressed).width(Length::Fill),
            )
        )

Portanto, o layout da janela deve ficar assim

4. Escreva a função principal

A janela escrita não pode ser executada automaticamente, ela precisa ser iniciada, geralmente inicie a janela na função principal, ficará mais fácil aqui, cole o código diretamente aqui

fn main() -> iced::Result {
    
    
    Counter::run(Settings::default())
}

Para iniciar a janela, basta chamar o método run da janela, que é passado em Configurações para definir o estado inicial da janela. Aqui, o estado padrão é usado diretamente. Se você quiser se aprofundar mais tarde, aqui haverá um especial problema para explicá-lo.

3. Efeito da operação

Neste ponto, executamos a demonstração atualmente escrita

注意:O código completo está no final do artigo, se você estiver com preguiça de digitar o código, pode copiá-lo diretamente.


Resumir

Esta edição apresenta a estrutura de GUI do Rust, Iced. Após minha exploração, finalmente construí o Counter Demo. Depois da minha experiência, acho que esse framework não é tão bom quanto eu imaginava. É realmente o framework GUI nativo do Rust e tem os recursos que ele disse. É realmente bonito, mas tem o maior problema. Não suporta chinês , e a linha e a coluna são estupidamente indistinguíveis. O documento oficial é muito antigo, então o processo de construção de uma demonstração torna-se muito complicado e não é muito amigável para o desenvolvimento. A única coisa que vale a pena mencionar é este código, que é realmente confortável Muito poucos, isso é inigualável por outros frameworks de interface do usuário. Isso é digno de aprovação. Espero que este framework ou seus sucessores possam resolver esses problemas no futuro, para que a interface do usuário do Rust possa se tornar mais forte.

código completo

use iced::{
    
    Alignment, button, Button, Column, Element, Length, Row, Sandbox, Settings, Text};

fn main() -> iced::Result {
    
    
    Counter::run(Settings::default())
}

struct Counter {
    
    
    value: i32,
    // The local state of the two buttons
    increment_button: button::State,
    decrement_button: button::State,
}

#[derive(Debug, Clone, Copy)]
enum Message {
    
    
    IncrementPressed,
    DecrementPressed,
}

impl Sandbox for Counter {
    
    
    type Message = Message;

    fn new() -> Self {
    
    
        Self {
    
     value: 0, increment_button: Default::default(), decrement_button: Default::default() }
    }

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

    fn update(&mut self, message: Message) {
    
    
        match message {
    
    
            Message::IncrementPressed => {
    
    
                self.value += 1;
            }
            Message::DecrementPressed => {
    
    
                self.value -= 1;
            }
        }
    }

    fn view(&mut self) -> Element<Message> {
    
    
        Column::new().push(
            Text::new("Counter")
        ).push(
            Row::new().push(
                Button::new(&mut self.increment_button, Text::new("+"))
                    .on_press(Message::IncrementPressed).width(Length::Fill),
            ).push(
                Text::new(self.value.to_string()).size(22),
            ).push(
                Button::new(&mut self.decrement_button, Text::new("-"))
                    .on_press(Message::DecrementPressed).width(Length::Fill),
            )
        )
        .align_items(Alignment::Center).into()
    }
}


Acho que você gosta

Origin blog.csdn.net/weixin_47754149/article/details/127271805
Recomendado
Clasificación