<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技术和人工智能的不断发展,数据的规模和种类也在快速增加。在这种背景下,传统的云计算模式面临着一些问题,例如延迟高、网络拥塞等,这些问题限制了数据的处理速度和效率,降低了用户的使用体验。为了解决…...
Ubuntu安装中文输入法后无法输入中文----问题分析及解决方法
问题:之前在Ubuntu系统上安装过搜狗输入法,且能正常输入中文。但重启之后无法调出,Shift切换也不管用,依旧是英文原因分析:后台进程(Fcitx)卡死或崩溃了解决方法:重启Fcitx输入法框架…...
从预测到归因:手把手教你用因果森林(grf)做特征重要性分析与亚组发现
从预测到归因:手把手教你用因果森林(grf)做特征重要性分析与亚组发现 在金融风控、个性化营销和医疗疗效评估等领域,我们常常面临一个关键问题:干预措施的效果是否存在显著差异?传统分析方法如A/B测试能告诉…...
新手避坑指南:PX4飞控连接TFmini、LIDAR Lite V3等定高雷达的完整接线与参数配置(QGC实操)
PX4飞控与定高雷达实战:从接线到参数配置的避坑指南 刚拿到PX4飞控和一堆传感器的新手们,面对密密麻麻的接口和参数设置,是不是有种无从下手的感觉?特别是当你需要连接定高雷达时,不同品牌(北醒TFmini、LID…...
快速体验WAN2.2文生视频:ComfyUI预置工作流,2分钟生成测试视频
快速体验WAN2.2文生视频:ComfyUI预置工作流,2分钟生成测试视频 1. 为什么选择WAN2.2文生视频工作流 如果你正在寻找一个简单易用、效果出色的文生视频工具,WAN2.2文生视频工作流绝对值得一试。这个预置在ComfyUI中的工作流,让视…...
通义千问3-VL-Reranker-8B保姆级部署教程:5分钟搞定Nginx反向代理与HTTPS配置
通义千问3-VL-Reranker-8B保姆级部署教程:5分钟搞定Nginx反向代理与HTTPS配置 1. 为什么需要反向代理与HTTPS 当你成功在本地运行通义千问3-VL-Reranker-8B服务后,默认只能通过 http://localhost:7860 访问。这种配置存在三个明显问题: 安…...
格式化字符串漏洞利用的5种常见手法:以CTFshow题目为例
格式化字符串漏洞实战:5种高级利用手法与CTFshow案例分析 格式化字符串漏洞(Format String Vulnerability)是二进制安全领域中最经典也最危险的漏洞类型之一。这种漏洞源于程序员错误地将用户输入直接作为格式化字符串参数传递给printf、spri…...
TD-ACC+实验系统入门指南:手把手教你搭建典型环节模拟电路
TD-ACC实验系统实战手册:从零构建典型环节电路的21个关键细节 第一次接触TD-ACC实验系统时,看着密密麻麻的接口和旋钮,我的手指悬在半空迟迟不敢落下——生怕一个错误的连接就会烧毁昂贵的运算放大器。这种忐忑直到成功捕捉到第一个完美方波信…...
ArduinoLog:面向MCU的零开销C++嵌入式日志框架
1. ArduinoLog 项目概述ArduinoLog 是一款专为 Arduino 及兼容嵌入式平台(包括 AVR、SAM、ESP8266 等)设计的轻量级 C 日志框架。其核心设计哲学是“零运行时开销、零动态内存分配、全编译期可控”,在资源极度受限的微控制器环境中࿰…...
深入解析STM32 map文件:从编译到内存优化的关键步骤
1. 为什么STM32开发者必须掌握map文件分析 第一次接触STM32的map文件时,我和大多数新手一样感到一头雾水。这个由编译器自动生成的文本文件,乍看就像天书般难以理解。直到有次项目遇到内存不足的紧急情况,我才真正体会到map文件的价值——它不…...
nlp_structbert_sentence-similarity_chinese-large 赋能智能客服:基于Vue前端的问题相似度匹配实践
nlp_structbert_sentence-similarity_chinese-large 赋能智能客服:基于Vue前端的问题相似度匹配实践 你有没有遇到过这种情况?在某个网站的客服对话框里,输入一个问题,等了半天,要么是机器人答非所问,要么…...
