<Rust><GUI>rust语言GUI库tauri体验:前、后端结合创建一个窗口并修改其样式
前言
本文是rust语言下的GUI库:tauri来创建一个窗口的简单演示,主要说明一下,使用tauri这个库如何创建GUI以及如何添加部件、如何编写逻辑、如何修改风格等,所以,这也是一个专栏,将包括tauri库的多个方面。

环境配置
系统:windows
平台:visual studio code
语言:rust、javascript、html、css
库:tauri
概述
本文是tauri库系列博文的第一篇,主要是简单实现一个窗口程序并成功运行,当然,这是基于官方的示例,事实上官方给出的上手例程非常详细,不过,本文在官方示例的基础上,将会做一些修改和延伸。
窗口示例
首先我们来看官方示例,tauri官方给出了一个新手教程,教导你如何快速创建并显示一个窗口,当然,这是最简单的窗口,不过,这个样例基本上涉及了tauri的整个原理。
首先,tauri是前后端结合的一种实现,它的页面创建、显示是使用的前端语言,你可以使用当前的任意前端语言来编写页面布局,比如:

我对前端编程不是很熟悉,因此选择了第一个即原生的javascript结合html和css来编写页面。
首先,在你的项目文件夹下,创建一个新文件夹,可以命名为ui,然后在ui文件夹下新建一个html文件,里面添加一些基本的内容:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>文档</title></head><body><h1>这是来自 Tauri 的欢迎!</h1></body>
</html>
以上内容,相信懂前端的朋友会很熟悉,如果你用浏览器运行这段代码,其显示如下:

所以,你应该了解了,tauri所谓的GUI其实就是和网页显示是一样的,只是封装成了窗口程序。这就是前端和后端的结合,前端使用的是html和js,后端呢,使用的则是rust。
好了,我们按照例程,新建了html文件,暂且先放着,然后我们要在项目路径下,创建rust文件。
对于初学者来说,官方建议使用tauri cli来管理rust代码,所以你需要先安装tauri cli:
cargo install tauri-cli
等待安装完成,然后来创建一个tauri下的rust项目:
cargo tauri init
当你运行这个指令时,tauri会让你“回答”几个问题,我们按照例程所示一一填写即可。
1、应用名称:输入你自定义的名字即可
2、窗口标题:就是生成的窗口的title,你可以输入一个自定义名称,后面也可以再修改
3、前端页面文件所在位置:输入你之前创建的ui文件夹路径,可以和官方一样使用"…/ui"这个路径,也可以根据你自己创建的文件夹路径来填写
4、开发环境时路径:和3一致
5、使用什么命令来开发前端:暂时不填
6、使用什么命令来构建前端:暂时不填
以上6个问题,填前4个就行,5、6暂时不填,因为涉及后期使用其他命令来开发前端的程序,但暂时你可能还不会或者不需要这样复杂的命令。

回答完问题后,tauri会自动创建一个包含rust代码的文件夹,通常文件夹名称默认为src-tauri,其目录层级如下:

我们先打开src文件夹下的main.rs文件,其内部代码如下:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]fn main() {
tauri::Builder::default().run(tauri::generate_context!()).expect("error while running tauri application");
}
main函数是rust程序的进入点,tauri在此创建窗口的初始化程序。
如果你这直接运行,使用cargo tauri dev
会得到一个和之前的网页所示一样画面的窗口画面。(首次编译时间可能会比较长)

以上是最简单的示例程序,基本上窗口是用html布局实现的,还没有涉及rust代码,下面看一下如何在html中调用rust函数来实现某些功能,比如实现文本内容的更改。
我们首先在main.rs中创建一个函数:
#[tauri::command]
fn greet(name: &str) -> String {format!("Hello, {}!", name)
}
这里,greet是rust中的普通函数,但是为其添加了#[tauri::command]宏,这样一来,greet函数就可以与js进行交互了。但是,还需要让tauri知道这个函数,所以需要注册它:
fn main() {tauri::Builder::default().invoke_handler(tauri::generate_handler![greet]).run(tauri::generate_context!()).expect("error while running tauri application");
}
如上,在原先的main函数里增加了一条.invoke_handler()函数,配合Generate_handler![]宏来注册greet函数。这样,就可以在前端代码里调用rust的函数功能了。
将之前的index.html代码修改一下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><h1 id="header">Welcome from Tauri!</h1><script>// access the pre-bundled global API functionsconst { invoke } = window.__TAURI__.tauri// now we can call our Command!// You will see "Welcome from Tauri" replaced// by "Hello, World!"!invoke('greet', { name: 'World' })// `invoke` returns a Promise.then((response) => {window.header.innerHTML = response})</script></body>
</html>
到此,都是官方提供的代码,对于前端的API调用,我不是很熟悉,但是我也不用管它,直接照做就行,目的是引用rust的函数,在上面的代码里,invoke后面的参数,第一个greet表示函数名,第二个是函数的参数名:
#[tauri::command]
fn greet(name: &str) -> String {format!("Hello, {}!", name)
}
invoke返回的是一个Pormise,据我粗浅的了解,Promise是一个异步操作,但这里并没有使用异步关键词,而是使用then来取得反馈response,关于前端,目前了解尚不多,所以此处我只关心其结果,根据官方示例,response就是函数greet运行后的输出,在此处的示例代码中,输出应该是:
Hello,World
然后将Hello,World传给当前页面的id为header的标签,即修改标签的内容为:
Hello,World
但是,需要注意的是,如果要rust中的注册函数起作用,需要修改一下tauri.conf.json文件的内容:
"build": {"beforeBuildCommand": "","beforeDevCommand": "","devPath": "../tau-ui","distDir": "../tau-ui","withGlobalTauri":true}
如上,在这个json文件里,为build选项添加withGlobalTauri参数,并将其设为true。
这是一个临时办法,在以后会使用 @tauri-apps/api包,但在目前的初学者教程里,不涉及这么复杂的内容。
再次运行程序:

以上,实现的是官方的示例程序,下面我们来作一下扩展,我们为页面添加一个按钮以及一条标签,然后点击按钮后,标签显示相应的内容,标签的内容由rust的函数提供。
所以,我们在main.rs中再添加一个函数:
#[tauri::command]
fn sendstring()->String{"来自rust的字符串".to_string()
}
然后注册到tauri:
fn main() {tauri::Builder::default().invoke_handler(tauri::generate_handler![greet,sendstring]).run(tauri::generate_context!()).expect("error while running tauri application");
}
然后,我们在index.html文件中添加一个按钮和标签:
<button id="btn1" onclick="">按钮1</button><p id="p1">hello,rust</p>
然后为按钮的点击事件绑定一个脚本函数:
<button id="btn1" onclick="recvstring()">按钮1</button>
function recvstring(){var elem=document.getElementById("p1");invoke('sendstring',{}).then((response)=>{elem.innerHTML=response;})}
然后再次运行程序:

点击按钮:

成功的执行了rust中注册的函数。
综上,tauri的使用体验,如果熟悉前端开发,我觉得还是不错的,因为虽然其后端使用的是rust,但是这仅在你的js无法满足开发的时候,我们就可以利用rust的强大功能来编写需要的函数,但是如果你要制作比较简单的程序,那么仅是js就完全满足开发了,就和开发网页程序是一样的,只是tauri封装成了桌面程序。
相比于iced以及egui这类rust的GUI库,我觉得 tauri的优点就是页面布局,感觉要方便很多,但目前我还没有去测试tauri的通讯,比如websocket等,不过,从体验上来说,tauri在github上排名rust gui库第一,的确是有道理的。
相关文章:
<Rust><GUI>rust语言GUI库tauri体验:前、后端结合创建一个窗口并修改其样式
前言 本文是rust语言下的GUI库:tauri来创建一个窗口的简单演示,主要说明一下,使用tauri这个库如何创建GUI以及如何添加部件、如何编写逻辑、如何修改风格等,所以,这也是一个专栏,将包括tauri库的多个方面。…...
OBD诊断(ISO15031) 09服务
文章目录 功能简介ISO 9141-2、ISO 14230-4和SAE J1850的诊断服务定义1、请求车辆信息请求消息(读取支持的INFOTYPE)2、请求车辆信息响应消息(报告支持INFOTYPE)3、请求车辆信息请求消息(读取INFOTYPE值)4、请求车辆信息响应消息&…...
客户端与服务端之间的通信连接
目录 那什么是Socket? 什么是ServerSocket? 代码展示: 代码解析: 补充: 输入流(InputStream): 输出流(OutputStream): BufferedReader 是如何提高读取效率的&a…...
Font Awesome 图表图标
Font Awesome 图表图标 Font Awesome 是一个广泛使用的图标库,它提供了大量的图标,可以轻松地用于网页设计和开发中。在本文中,我们将重点介绍 Font Awesome 中的图表图标,探讨它们的特点、使用方法,并展示一些实际的…...
React Native 自定义 Hook 获取组件位置和大小
在 React Native 中自定义 Hook useLayout 获取 View、Pressable 等组件的位置和大小的信息 import {useState, useCallback} from react import {LayoutChangeEvent, LayoutRectangle} from react-nativeexport function useLayout() {const [layout, setLayout] useState&l…...
如何在SpringCloud中使用Kafka Streams实现实时数据处理
使用Kafka Streams在Spring Cloud中实现实时数据处理可以帮助我们构建可扩展、高性能的实时数据处理应用。Kafka Streams是一个基于Kafka的流处理库,它可以用来处理流式数据,进行流式计算和转换操作。 下面将介绍如何在Spring Cloud中使用Kafka Streams实…...
InterSystems IRIS使用python pyodbc连接 windows环境,odbc驱动安装,DSN配置,数据源配置
一、创建的数据库和数据 SELECT 1SELECT $ZVERSIONCREATE TABLE MyApp.Person ( ID INT PRIMARY KEY, Name VARCHAR(100) NOT NULL, Age INT, Gender CHAR(1) );CREATE TABLE MyApp.Person2 ( ID INT PRIMARY KEY, Name VARCHAR(100) NOT NULL, Age INT, Gender CHA…...
JVM:运行时数据区
文章目录 一、总览二、程序计数器1、介绍2、程序计数器在运行中会出现内存溢出吗? 三、栈1、介绍2、栈帧的组成部分(1)局部变量表(2)操作数栈(3)帧数据(3)栈内存溢出&…...
spring-boot2.x整合Kafka步骤
1.pom依赖添加 <properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</ma…...
信创学习笔记(四),信创之数据库DB思维导图
创作不易 只因热爱!! 热衷分享,一起成长! “你的鼓励就是我努力付出的动力” 一. 信创学习回顾 1.信创内容 信创内容思维导图 2.信创之CPU芯片架构 信创之CPU芯片架构思维导图 3.信创之操作系统OS 信创之操作系统OS思维导图 二. 信创之国产数据库DB思维导图 …...
SCP 使用教程
SCP(Secure Copy Protocol)是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。它是基于SSH协议的扩展,允许用户在不同主机之间进行文件复制和传输,是Linux和Unix系统中常用的工具之一。本教程将详细介绍SCP的基…...
python自动化之用flask校验接口token(把token作为参数)
用到的库:flask 实现效果: 写一个接口,需要token正确才能登录 代码: # 导包 from flask import Flask,request,jsonify,json # 创建一个服务 appFlask(__name__) # post请求,路径:/query app.route(/query, met…...
旗晟巡检机器人的应用场景有哪些?
巡检机器人作为现代科技的杰出成果,已广泛应用于各个关键场景。从危险的工业现场到至关重要的基础设施,它们的身影无处不在。它们以精准、高效、不知疲倦的特性,担当起保障生产、守护安全的重任,为行业发展注入新的活力。那么&…...
vue2迁移到vue3注意点
vue2迁移到vue3注意点 1、插槽的修改 使用 #default , 以及加上template 模板 2、 类型的定义,以及路由,vue相关资源(ref, reactive,watch)的引入等 3、类装饰器 1)vue-class-component是vue官方库,作…...
使用windows批量解压和布局ImageNet ISLVRC2012数据集
使用的系统是windows,找到的解压命令很多都linux系统中的,为了能在windows系统下使用,因此下载Git这个软件,在其中的Git Bash中使用以下命令,因为Git Bash集成了很多linux的命令,方便我们的使用。 ImageNe…...
css实现每个小盒子占32%,超出就换行
代码 <div class"visitors"><visitor class"item" v-for"(user,index) in userArr" :key"user.id" :user"user" :index"index"></visitor></div><style lang"scss" scoped&…...
C++的链接指示extern “C“
目录 链接指示extern "C"A.What(概念)B.Why(extern "C"的作用)C.How (如何使用链接指示extern "C") 链接指示extern “C” A.What(概念) extern&quo…...
私域运营 组织架构
**揭秘私域社群运营的神秘面纱:角色与职能一网打尽!** 在私域社群运营的大舞台上,每个角色都扮演着不可或缺的重要角色。今天,就让我们一起揭开这个神秘世界的面纱,看看这些角色们是如何协同作战,共同创造…...
Netty HTTP
Netty 是一个高性能的异步事件驱动的网络应用程序框架,支持快速开发可维护的高性能协议服务器和客户端。它广泛应用于开发网络应用程序,如服务器和客户端协议的实现。Netty 提供了对多种传输类型的抽象,如 TCP/IP 和 UDP/IP 等,使…...
什么是边缘计算技术和边缘计算平台?
随着物联网、5G技术和人工智能的不断发展,数据的规模和种类也在快速增加。在这种背景下,传统的云计算模式面临着一些问题,例如延迟高、网络拥塞等,这些问题限制了数据的处理速度和效率,降低了用户的使用体验。为了解决…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
