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

相关文章
|
传感器 运维 物联网
蓝牙Mesh网络:连接未来的智能解决方案
蓝牙Mesh网络:连接未来的智能解决方案
1824 12
|
12月前
|
JavaScript 前端开发 中间件
探索后端技术:Node.js与Express框架的完美融合
【10月更文挑战第7天】 在当今数字化时代,Web应用已成为日常生活不可或缺的一部分。本文将深入探讨后端技术的两大重要角色——Node.js和Express框架,分析它们如何通过其独特的特性和优势,为现代Web开发提供强大支持。我们将从Node.js的非阻塞I/O和事件驱动机制,到Express框架的简洁路由和中间件特性,全面解析它们的工作原理及应用场景。此外,本文还将分享一些实际开发中的小技巧,帮助你更有效地利用这些技术构建高效、可扩展的Web应用。无论你是刚入门的新手,还是经验丰富的开发者,相信这篇文章都能为你带来新的启发和思考。
|
8月前
|
安全 算法 物联网
SSL/TLS:互联网通信的加密基石与安全实践
**简介:** 在数字化时代,互联网每天传输海量敏感数据,网络攻击频发。SSL/TLS协议作为网络安全的基石,通过加密技术确保数据安全传输。本文解析SSL/TLS的技术架构、密码学原理、应用场景及常见误区,探讨其在未来的发展趋势,强调持续演进以应对新型威胁的重要性。 SSL/TLS不仅保障Web安全,还广泛应用于API、邮件、物联网等领域,并遵循合规标准如PCI DSS和GDPR。
|
关系型数据库 Serverless 定位技术
PostgreSQL GIS函数判断两条线有交点的函数是什么?
PostgreSQL GIS函数判断两条线有交点的函数是什么?
815 60
|
11月前
|
缓存 安全 算法
SSL和TLS部署实践
在TLS中,所有安全性都以服务器的加密身份开始,这就需要一个强大的私钥来防止攻击者进行模拟攻击。同样重要的是拥有一个有效和强大的证书,它会授予私钥来代表一个特定的主机名。
289 2
|
Rust JavaScript 前端开发
【一起学Rust | 框架篇 | iced框架】rust原生跨平台GUI框架——iced
【一起学Rust | 框架篇 | iced框架】rust原生跨平台GUI框架——iced
1492 0
|
Java Maven
Java系列之:GroupId和ArtifactId的作用
这篇文章解释了在Maven项目中`GroupId`和`ArtifactId`的含义和作用,其中`GroupId`通常由域和自定义域名组成,用于区分组织或公司,而`ArtifactId`是项目或模块的名称,两者结合用于唯一标识项目包,确保不会与他人的项目包重复。
|
Rust 前端开发 JavaScript
Tauri框架:使用Rust构建轻量级桌面应用
Tauri是一个用Rust构建的开源框架,用于创建轻量、安全且高效的跨平台桌面应用,结合Rust与Web技术(HTML/CSS/JS)。它遵循最小权限原则,仅在必要时调用OS API。Tauri架构包括Rust后端、Web前端、Tauri API和包装器。通过`cargo tauri init`可创建新项目,Rust后端处理系统交互,前端负责UI,两者通过Tauri API通信。Tauri支持自定义API、集成前端框架、资源管理、自动更新、系统集成和安全配置。此外,Tauri拥有插件系统和丰富的扩展能力,提供调试和测试工具,并有性能优化建议。
884 4
|
Linux 开发工具 C++
技术笔记:NanoGUI使用
技术笔记:NanoGUI使用
245 0