技术笔记:RustGUI编程

简介: 技术笔记:RustGUI编程

目录


1.可以用iced框架,star比较多,而且在快速发展中,源码跨平台;


2.在main方法文件最上面加上:#!【windows_subsystem = "windows"】,这样Windows平台运行编译好的gui程序时就不会弹出控制台框;


对于Mac OS,Linux可以自己写个图标配置(Linux是.desktop文件)就可以直接双击图标来打开程序而非必须先开一个控制台,所以这两个平台没有这个全局宏。


3.iced使用示例:根据官网示例写一个加减的按钮和显示:


Cargo.toml:(这个配置兼容性不好,换成下面代码块里的)


【package】


name = "demo-iced"


version = "0.1.0"


authors = 【"silentdoer "】


edition = "2018"


# See more keys and their definitions at


【dependencies】


iced = { git = "", features = 【"async-std", "debug"】 } # debug考虑不要


iced_web = "0.2"


serde = { version = "1.0", features = 【"derive"】 }


serde_json = "1.0"


【target.'cfg(not(target_arch = "wasm32"))'.dependencies】


async-std = "1"


directories = "2"


【target.'cfg(target_arch = "wasm32")'.dependencies】


web-sys = { version = "0.3", features = 【"Window", "Storage"】 }


wasm-timer = "0.2"


【package.metadata.deb】


assets = 【


【"target/release/todos", "usr/bin/iced-todos", "755"】,


【"iced-todos.desktop", "usr/share/applications/", "644"】,



上面的Cargo.toml配置有几个问题,第一是必需是vs2017或以上,第二就是debug模式编译的程序运行有问题,第三个就是需要编译的模块很多,第四个是win10编译出的release程序(debug是win10都运行有问题)win10可以用,但是win7运行失败(经过测试win7编译出的win10可以运行,但是win10编译出的在win7上仍然运行失败(2017,2015,gnu三个都失败了,等会再换2013和2012【2012直接编译失败,哪怕是OpenGL的】的C++如果还失败那只能在win7上编译Windows全平台了【或者测试下Ubuntu跨平台编译的gui程序是否可以同时在win10和win7上运行】));(当然也有好处,上面的配置用的GUI后端是DX或vulkan,而接下来的配置用的是OpenGL效率没上面的高【注意,不需要安装OpenGL,win10和win7里都有】)


【这种方式编译出来的程序也有问题,就是它放到一个没有安装过C++环境的系统里运行不了。。。坑啊,目前没有比较好的解决方案,暂时还是用第一种算了,然后win10和win7都以release编译一下(刚才又查了下说也可能是显卡驱动的原因。。)】


【package】


name = "demo-iced"


version = "0.1.0"


authors = 【"silentdoer "】


edition = "2018"


# See more keys and their definitions at


【dependencies】


iced = { git = "", default-features = false, features = 【"async-std", "debug", "glow"】 }


serde = { version = "1.0", features = 【"derive"】 }


serde_json = "1.0"


【target.'cfg(not(target_arch = "wasm32"))'.dependencies】


async-std = "1"


directories = "2"


【target.'cfg(target_arch = "wasm32")'.dependencies】


web-sys = { version = "0.3", features = 【"Window", "Storage"】 }


wasm-timer = "0.2"


【package.metadata.deb】


assets = 【


【"target/release/todos", "usr/bin/iced-todos", "755"】,


【"iced-todos.desktop", "usr/share/applications/", "644"】,



在项目根目录添加fonts目录,里面将Windows的simkai.ttf字体复制进去


main.rs:


#!【windows_subsystem = "windows"】


use iced::{


button, scrollable, text_input, Align, Application, Button, Checkbox,


Column, Command, Container, Element, Font, HorizontalAlignment, Length,


Row, Scrollable, Settings, Text, TextInput,


};


use serde::{Deserialize, Serialize};


pub fn main() {


Todos::run(Settings {


default_font: Some(include_bytes!("../fonts/simkai.ttf")),


..Settings::default()


})


}


#【derive(Debug)】


enum Todos {


Loading,


Loaded(State),


}


#【derive(Debug, Default)】


struct State {


scroll: scrollable::State,


input: text_input::State,


input_value: String,


filter: Filter,


tasks: Vec,


controls: Controls,


dirty: bool,


saving: bool,


}


#【derive(Debug, Clone)】


enum Message {


Loaded(Result),


Saved(Result),


InputChanged(String),


CreateTask,


FilterChanged(Filter),


TaskMessage(usize, TaskMessage),


}


impl Application for Todos {


type Executor = iced::executor::Default;


type Message = Message;


type Flags = ();


fn new(_flags: ()) -> (Todos, Command) {


(


Todos::Loading,


Command::perform(SavedState::load(), Message::Loaded),


)


}


fn title(&self) -> String {


let dirty = match self {


Todos::Loading => false,


Todos::Loaded(state) => state.dirty,


};


format!("Todos{} - Iced", if dirty { "" } else { "" })


}


fn update(&mut self, message: Message) -> Command {


match self {


Todos::Loading => {


match message {


Message::Loaded(Ok(state)) => {


self = Todos::Loaded(State {


input_value: state.inputvalue,


filter: state.filter,


tasks: state.tasks,


..State::default()


});


}


Message::Loaded(Err()) => {


self = Todos::Loaded(State::default());


}


_ => {}


}


Command::none()


}


Todos::Loaded(state) => {


let mut saved = false;


match message {


Message::InputChanged(value) => {


state.input_value = value;


}


Message::CreateTask => {


if !state.input_value.is_empty() {


state


.tasks


.push(Task::new(state.input_value.clone()));


state.input_value.clear();


}


}


//代码效果参考:http://www.lyjsj.net.cn/wx/art_23238.html

Message::FilterChanged(filter) => {

state.filter = filter;


}


Message::TaskMessage(i, TaskMessage::Delete) => {


state.tasks.remove(i);


}


Message::TaskMessage(i, task_message) => {


if let Some(task) = state.tasks.get_mut(i) {


task.update(taskmessage);


}


}


Message::Saved() => {


state.saving = false;


saved = true;


}


_ => {}


}


if !saved {


state.dirty = true;


}


if state.dirty && !state.saving {


state.dirty //代码效果参考:http://www.lyjsj.net.cn/wz/art_23236.html

= false;

state.saving = true;


Command::perform(


SavedState {


input_value: state.input_value.clone(),


filter: state.filter,


tasks: state.tasks.clone(),


}


.save(),


Message::Saved,


)


} else {


Command::none()


}


}


}


}


fn view(&mut self) -> Element {


match self {


Todos::Loading => loading_message(),


Todos::Loaded(State {


scroll,


input,


input_value,


filter,


tasks,


controls,


..


}) => {


let title //代码效果参考:http://www.lyjsj.net.cn/wz/art_23226.html

= Text::new("todos")

.width(Length::Fill)


.size(100)


.color(【0.5, 0.5, 0.5】)


.horizontal_alignment(HorizontalAlignment::Center);


let input = TextInput::new(


input,


"What needs to be done?",


input_value,


Message::InputChanged,


)


.padding(15)


.size(30)


.on_submit(Message::CreateTask);


let controls = controls.view(&tasks, filter);


let filtered_tasks =


tasks.iter().filter(|task| filter.matches(task));


let tasks: Element = if filtered_tasks.count() > 0 {


tasks


.itermut()


.enumerate()


.filter(|(, task)| filter.matches(task))


.fold(Column::new().spacing(20), |column, (i, task)| {


column.push(task.view().map(move |message| {


Message::TaskMessage(i, message)


}))


})


.into()


} else {


empty_message(match filter {


Filter::All => "You have not created a task yet...",


Filter::Active => "All your tasks are done! :D",


Filter::Completed => {


"You have not completed a task yet..."


}


})


};


let content = Column::new()


.max_width(800)


.spacing(20)


.push(title)


.push(input)


.push(controls)


.push(tasks);


Scrollable::new(scroll)


.padding(40)


.push(


Container::new(content).width(Length::Fill).center_x(),


)


.into()


}


}


}


}


#【derive(Debug, Clone, Serialize, Deserialize)】


struct Task {


description: String,


completed: bool,


#【serde(skip)】


state: TaskState,


}


#【derive(Debug, Clone)】


pub enum TaskState {


Idle {


edit_button: button::State,


},


Editing {


text_input: text_input::State,


delete_button: button::State,


},


}


impl Default for TaskState {


fn default() -> Self {


TaskState::Idle {


edit_button: button::State::new(),


}


}


}


#【derive(Debug, Clone)】


pub enum TaskMessage {


Completed(bool),


Edit,


DescriptionEdited(String),


FinishEdition,


Delete,


}


impl Task {


fn new(description: String) -> Self {


Task {


description,


completed: false,


state: TaskState::Idle {


edit_button: button::State::new(),


},


}


}


fn update(&mut self, message: TaskMessage) {


match message {


TaskMessage::Completed(completed) => {


self.completed = completed;


}


TaskMessage::Edit => {


self.state = TaskState::Editing {


text_input: text_input::State::focused(),


delete_button: button::State::new(),


};


}


TaskMessage::DescriptionEdited(new_description) => {


self.description = new_description;


}


TaskMessage::FinishEdition => {


if !self.description.is_empty() {


self.state = TaskState::Idle {


edit_button: button::State::new(),


}


}


}


TaskMessage::Delete => {}


}


}


fn view(&mut self) -> Element {


match &mut self.state {


// 重要


TaskState::Idle { edit_button } => {


let checkbox = Checkbox::new(


self.completed,


&format!("{}{}", self.description, "*").to_string(),


TaskMessage::Completed,


)


.width(Length::Fill);


Row::new()


.spacing(20)


.align_items(Align::Center)


// 空闲状态时,左侧一个checkbox,右侧的button样式是Icon


.push(checkbox)


.push(


// edit_button是state数据,edit_icon()返回的是一个Unicode字符作为显示字符(浏览器上不一致应该是fonts的原因)


Button::new(edit_button, edit_icon())


.on_press(TaskMessage::Edit)


.padding(10)


.style(style::Button::Icon),


)


.into()


}


// 当变为Editing状态时的view变化(要变成红色Delete)


TaskState::Editing {


text_input,


delete_button,


} => {


let text_input = TextInput::new<span style="

相关文章
|
9月前
|
JavaScript 前端开发
JavaScriptDOM编程(基础&进阶)2
JavaScriptDOM编程(基础&进阶)2
34 0
|
11天前
|
存储 人工智能 算法
计算机编程:从基础到实践,探索编程的奥秘
计算机编程:从基础到实践,探索编程的奥秘
10 1
|
1月前
|
设计模式 算法 测试技术
探索代码之美:我的编程思考之旅
【5月更文挑战第8天】 在数字化的浪潮中,编程已成为一种艺术,一种用逻辑与创造力编织的语言。本文将分享我在编程实践中的一些技术感悟,从最初的困惑到逐渐的深入理解,再到最后的灵活应用,我经历了一段充满挑战与收获的旅程。文章不仅探讨了编程技巧的提升,还涉及了对软件设计原则的认识,以及如何通过不断学习来适应快速变化的技术环境。
|
1月前
|
自然语言处理 Java 编译器
【软件设计师—基础精讲笔记10】第十章 程序设计语言基础
【软件设计师—基础精讲笔记10】第十章 程序设计语言基础
42 1
|
1月前
|
设计模式 存储 算法
【软件设计师—基础精讲笔记7】第七章 面向对象技术
【软件设计师—基础精讲笔记7】第七章 面向对象技术
65 1
|
1月前
|
存储 设计模式 人工智能
程序设计:原理、实践与魅力
程序设计:原理、实践与魅力
36 0
|
1月前
|
网络协议 Unix Linux
Linux应用开发基础知识——网络通信编程(九)
Linux应用开发基础知识——网络通信编程(九)
66 0
Linux应用开发基础知识——网络通信编程(九)
|
Java C#
【c#入门杂选】-带你熟知c#基础知识点《思维导图》
【c#入门杂选】-带你熟知c#基础知识点《思维导图》
140 0
|
JavaScript Java 编译器
编程简单科普系列 - 什么是编程 (1)
广义上来说,编程也不仅仅是指关于计算机的范畴,现在通常也指可以diy的东西,可以通过自己想法进行自定义的东西。当然我们这里所说的是指计算机编程. 因为计算机是不能直接听懂我们人说话的,没办法直接沟通,所以我们需要通过编程语言来跟计算机进行沟通,通过编程语言把我们想表达的转化为计算机能听懂的,在这里编程语言就相当一个翻译(比如,我们不会英文,准备要和一说英文的外国人谈生意,这时候就需要找一个英文翻译,替我们把想要表达的中文翻译成对方听得懂的英文。)其实严谨点这个比喻说也不准确,因为编程语言一般是需要通过编译器或者解释器编译解释之后,才能为计算机所识别. 每个计算机编程语言,都有自己的编译器或者解
317 0
|
消息中间件 存储 安全
重新开始学习编程系列Day01——编程入门
计算机基础知识,操作系统以及内存知识,重新开始学习计算机,学习编程
743 0
重新开始学习编程系列Day01——编程入门