技术笔记: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="

相关文章
|
算法 JavaScript 前端开发
【如何入门编程】
【如何入门编程】
115 0
|
XML 移动开发 JavaScript
JavaScriptDOM编程(基础&进阶)1
JavaScriptDOM编程(基础&进阶)1
57 0
|
JavaScript 前端开发
JavaScriptDOM编程(基础&进阶)3
JavaScriptDOM编程(基础&进阶)3
60 0
|
JavaScript 前端开发
JavaScriptDOM编程(基础&进阶)2
JavaScriptDOM编程(基础&进阶)2
52 0
|
2月前
|
人工智能 数据挖掘 数据处理
揭秘Python编程之美:从基础到进阶的代码实践之旅
【9月更文挑战第14天】本文将带领读者深入探索Python编程语言的魅力所在。通过简明扼要的示例,我们将揭示Python如何简化复杂问题,提升编程效率。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编码世界的大门。让我们开始这段充满智慧和乐趣的Python编程之旅吧!
|
1天前
|
机器学习/深度学习 数据采集 数据挖掘
Python编程语言的魅力:从入门到进阶的全方位解析
Python编程语言的魅力:从入门到进阶的全方位解析
|
1月前
|
数据采集 数据挖掘 数据处理
探索Python编程:从基础到进阶的旅程
在编程世界中,Python因其易学性和强大功能而受到许多开发者的青睐。本文将通过一系列生动的例子和实用的技巧,带领初学者理解Python的基础概念,并逐步深入到更复杂的编程任务。我们将一起探索如何通过Python解决实际问题,同时提升编程技能和逻辑思维能力。无论你是编程新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的学习资源和灵感。
|
1月前
|
存储 数据处理 开发者
深入浅出:Python编程基础与实战技巧
【9月更文挑战第32天】本文将引导读者从零开始,掌握Python编程语言的核心概念,并通过实际代码示例深入理解。我们将逐步探索变量、数据结构、控制流、函数、类和异常处理等基本知识,并结合实用案例,如数据处理、文件操作和网络请求,提升编程技能。无论您是初学者还是有一定经验的开发者,这篇文章都能帮助您巩固基础,拓展视野。
26 3
|
2月前
|
机器学习/深度学习 程序员 Python
掌握Python编程:从基础到进阶的旅程
【9月更文挑战第11天】在这篇文章中,我们将一起踏上Python编程的学习之旅。无论你是初学者还是希望提升自己的技能,这篇文章都将为你提供一条清晰的道路。我们将从Python的基本概念出发,逐步深入到更复杂的主题,如面向对象编程、异常处理和模块使用。通过这篇文章,你将获得必要的知识和技能,以便在Python编程世界中自信地迈出每一步。
|
3月前
|
存储 Java 开发者
Java编程之旅:从基础到深入
【8月更文挑战第31天】本文将带你踏上Java编程的奇妙旅程,从零基础出发,逐步深入到Java的世界。我们将一起探索Java的基本语法、面向对象编程、集合框架、异常处理等核心概念,并通过实际代码示例加深理解。无论你是编程初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的参考和启示。