Diretório de artigos
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 value
representam o valor da contagem do contador increment_button
e decrement_button
o 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 é IncrementPressed
para representar o botão + foi clicado e a outra é para DecrementPressed
representar 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 IncrementPressed
o botão + foi clicado. Se for clicado, o valor do estado será +1. A outra é que DecrementPressed
o 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()
}
}