当前位置: 首页 > news >正文

【Tauri2】046—— tauri_plugin_clipboard_manager(一)

目录

前言

正文

安装

Rust中的使用

对文字的操作

看看write_text的函数签名

看看read_text的函数签名

对图像的操作

对html的操作

总结


前言

这篇就来看看clipboard这个插件。

参考如下

Clipboard | Taurihttps://tauri.app/plugin/clipboard/


正文

安装

执行下面的命令

pnpm tauri add clipboard-manager

前后端同时安装这个插件,并且注册插件

        .plugin(tauri_plugin_clipboard_manager::init())

这个插件 的英文意思在这里指的是(计算机上的)剪贴板

CLIPBOARD中文(简体)翻译:剑桥词典https://dictionary.cambridge.org/zhs/%E8%AF%8D%E5%85%B8/%E8%8B%B1%E8%AF%AD-%E6%B1%89%E8%AF%AD-%E7%AE%80%E4%BD%93/clipboard


Rust中的使用

要想在Rust中使用,需要导入一个关键的trait

use tauri_plugin_clipboard_manager::ClipboardExt;

许多插件都有这个操作,比如Shell、Opener。

剪贴板上面有什么东西——有文本、图片。

对文字的操作

显而易见,需要先写文字在剪贴版上,才能粘贴文字。因此,代码如下

#[command]
fn read_text(app_handle: AppHandle)-> String {app_handle.clipboard().write_text("start").unwrap();app_handle.clipboard().read_text().unwrap()
}

看看write_text的函数签名

 pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) 
-> crate::Result<()>

需要传一个参数text,泛型是T,泛型约束是Into<Cow<'a, str>>

表示接受任何能转换为 Cow<'a, str> 的类型,比如传String、&str、Cow。

use std::borrow::Cow;    
app_handle.clipboard().write_text(Cow::Borrowed("start")).unwrap();

声明生命周期'a。返回Result。

看看read_text的函数签名

pub fn read_text(&self) -> crate::Result<String>

返回Result<String>。

注册通信并使用,不必细说。

对图像的操作

同理,先要有图像,然后才能粘贴图像。

前面写入文字使用的是write_text,那么粘贴图像——write_image

函数签名如下

 pub fn write_image(&self, image: &Image<'_>) -> crate::Result<()> 

传入一个&Image

前面读取文字使用的是read_text,那么粘贴图像——read_image

函数签名如下

pub fn read_image(&self) -> crate::Result<Image<'_>> 

返回一个Result,其中的类型是Image。

模仿前面,作出一些细微的修改,代码如下

#[command]
fn image(app_handle: AppHandle) -> Result<Image<'static>> {app_handle.clipboard().write_image(&Image::from_path("./icons/icon.png").unwrap()).unwrap();let image=app_handle.clipboard().read_image().unwrap();Ok(image)
}

说起来,还从来没写过在通信函数中返回Image的,还没见过。

上面这段代码,首先需要添加feature ,即在Cargo.toml文件中

tauri= {version = "2.5.1", features = ["image-ico"] }

或者

tauri= {version = "2.5.1", features = ["image-png"] }

运行,然后报错

error[E0515]: cannot return value referencing function parameter `app_handle`
  --> src\main.rs:27:5
   |
27 |     app_handle.clipboard().read_image().unwrap()
   |     ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |     |
   |     returns a value referencing data owned by the current function
   |     `app_handle` is borrowed here

 直接翻译,意思是返回了一个引用了当前函数所拥有数据的值,app_handle在此处被借用

所有权问题——返回值依赖于app_handle的内部数据,当函数结束时数据将被释放,但返回值却试图继续引用它们,这会导致悬垂指针(dangling pointer)问题。

因此,获取所有权,即

    app_handle.clipboard().read_image().unwrap().to_owned()

还有其他类似方法。

后面注册通信函数,又报错了

关键报错如下

16 | pub struct Image<'a> {
   | -------------------- doesn't satisfy `tauri::image::Image<'_>: IpcResponse`
   |
   = note: the following trait bounds were not satisfied:
           `tauri::image::Image<'_>: IpcResponse`
           which is required by `&tauri::image::Image<'_>: tauri::ipc::private::ResponseKind`
   = note: this error originates in the macro `__cmd__image` which comes from the expansion of the macro `tauri::generate_handler` (in Nightly builds, run with -Z macro-backtrace for more info)

意思就是Image没有实现 IpcResponse 这个trait,如果为其实现这个trait

考虑一个关键的东西——孤儿规则

Image 是 tauri 中的类型,IpcResponse 是 tauri 中的 trait。

因为孤儿规则限制,除非在 Tauri 的源代码中修改,否则无法直接为 Image 实现 IpcRespons这个trait

无法直接实现。

Rust: trait 孤儿规则_rust孤儿原则-CSDN博客https://blog.csdn.net/wowotuo/article/details/88594502

rust学习二十.9、RUST绕过孤儿规则实现特质和包装器缺点 - 正在战斗中 - 博客园https://www.cnblogs.com/lzfhope/p/18807962可以创建一个包装类型(newtype)来绕过孤儿规则,笔者在后续试试,在这篇就不尝试了。

因此,返回Image可能比较困难,如果将其变成字节数组,比如to_bytes这样的方法。

笔者看到了Image结构体的定义

#[derive(Debug, Clone)]
pub struct Image<'a> {rgba: Cow<'a, [u8]>,width: u32,height: u32,
}

这个rgba好像就是字节数组。

因此,重新修改一下,就返回里面东西,代码如下。

#[command]
fn image(app_handle: AppHandle) -> Result<(Vec<u8>, u32, u32)> {app_handle.clipboard().write_image(&Image::from_path("./icons/icon.png").unwrap()).unwrap();let image = app_handle.clipboard().read_image().unwrap();let rgba = image.rgba().to_owned();let w = image.width();let h = image.height();Ok((rgba, w, h))
}

注册通信函数并使用,结果如下

前端结果

可以发现,第一个参数是一个数组,既然如此,展示一下。

前端代码如下

import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";export default function Home() {const [imageUrl, setImageUrl] = useState("");// 定义后端返回的数据类型type ImageData = [number[], number, number];async function clicked() {setImageUrl("");try {const [rgba, width, height]: ImageData = await invoke("image");// 创建 Canvasconst canvas = document.createElement("canvas");canvas.width = width;canvas.height = height;const ctx = canvas.getContext("2d");if (!ctx) {console.error("无法获取 Canvas 上下文");return;}// 将 RGBA 字节转换为 ImageDataconst imageData = new ImageData(new Uint8ClampedArray(rgba), width, height);ctx.putImageData(imageData, 0, 0);// 转换为 data URLconst url = canvas.toDataURL("image/png");setImageUrl(url);} catch (error) {console.error("错误:", error);}}return (<div><h1>Home</h1><p>首页</p><button onClick={clicked}>点击</button><div>{imageUrl ? (<img src={imageUrl} alt="Generated Image" style={{ maxWidth: "100%" }} />) : (<p>点击按钮加载图像</p>)}</div></div>);
}

结果如下

没问题。

感觉逻辑不是很对,应该是复制了一张图片,然后粘贴就出现图片。

这就要在前端使用这个插件,后面再说。

对html的操作

看了对文字和图片的操作,接下来看看对html文本的操作。

对html的操作,只有一个方法,

    pub fn write_html<'a, T: Into<Cow<'a, str>>>(&self,html: T,alt_text: Option<T>,) -> crate::Result<()> 

传两个参数,一个是html,另一个是Option,返回Result<()>。没有返回值。

代码如下

#[command]
fn html(app_handle: AppHandle){app_handle.clipboard().write_html("<h1>hello start!</h1>",Some("hello start!"));let a=app_handle.clipboard().read_text().unwrap();println!("a: {}", a);}

或者写

.write_html("<h1>hello start!</h1>", None::<&str>)

都行,

注册通信函数并运行。结果如下

可以发现,打印的hello start!,如果是None,

什么都没有。


总结

这个插件在Rust的部分的使用就介绍到这,后续再看看在前端的使用。

逻辑有点怪,应该是复制,然后粘贴,而不是直接写入。

相关文章:

  • RVTools 官网遭入侵,被用于分发携带 Bumblebee 恶意软件的篡改安装包
  • SUI批量转账几种方法介绍
  • 谈谈对《加密算法》的理解
  • PyTorch中单卡训练、DataParallel(DP)和DistributedDataParallel(DDP)
  • 如何自己建设网站?
  • 第6章 C控制语句:循环
  • Java转Go日记(四十三):Gorm事务
  • 反射在spring boot自动配置的应用
  • HTML应用指南:利用POST请求获取全国申通快递服务网点位置信息
  • 基于Java的校园失物招领系统【附源码】
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月20日第83弹
  • Python----循环神经网络(WordEmbedding词嵌入)
  • Java中的ImageIo支持webp解析
  • java中的Filter使用详解
  • Leetcode 01 java
  • 预先学习:构建智能系统的 “未雨绸缪” 之道
  • 杰发科技AC7840——如何把结构体数据写到Dflash中
  • 【NLP 76、Faiss 向量数据库】
  • 珈和科技贺李德仁院士荣膺国际数字地球学会会士:以时空智能赋能可持续发展目标 绘就数字地球未来蓝图
  • 【神经网络与深度学习】扩散模型之通俗易懂的解释
  • 巴基斯坦西南部一辆客车遭袭造成至少4死30伤
  • 权威访谈丨国家疾控局就《世界卫生组织大流行协定》答记者问
  • 中公教育:现阶段在全力解决学员退费问题,部分地区历史退费已逐步出清
  • 杨国荣︱以经验说事:思想史研究中一种需要反思的现象
  • 大学2025丨苏大教授王尧:文科最大的危机是阐释世界的能力弱化
  • AG600“鲲龙”批生产首架机完成生产试飞