如何在TypeScript中引入,Qt框架的webchannel:
我的工程环境为:Vite React TypeScript
第一步:引入 qtwebchannel.js,并将你的qtwebchannel.js放在public下,假如是将public作为资源目录
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline';"
/> -->
<title>SCAN NEO</title>
</head>
<body>
<div id="root"></div>
<script src="/qwebchannel.js"></script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
第二步:定义全局 types,并且导出
declare namespace QWebChannel {
export interface MessageTypes {
signal: 1;
propertyUpdate: 2;
init: 3;
idle: 4;
debug: 5;
invokeMethod: 6;
connectToSignal: 7;
disconnectFromSignal: 8;
setProperty: 9;
response: 10;
}
export interface Transport {
send(data: any): void;
onmessage?: (message: { data: any }) => void;
}
export class QObject {
constructor(name: string, data: any, webChannel: QWebChannel);
__id__?: string;
__objectSignals__?: { [key: string]: Function[] };
__propertyCache__?: { [key: string]: any };
unwrapQObject?(response: any): any;
unwrapProperties?(): void;
propertyUpdate?(signals: any, propertyMap: any): void;
signalEmitted?(signalName: string, signalArgs: any[]): void;
}
}
declare class QWebChannel {
constructor(
transport: QWebChannel.Transport,
initCallback?: (channel: QWebChannel) => void,
);
send(data: any): void;
exec(data: any, callback?: (data: any) => void): void;
objects: { [key: string]: QWebChannel.QObject };
debug: boolean;
static init(transport: QWebChannel.Transport): Promise<QWebChannel>;
}
// 扩展全局 Window 接口
declare global {
interface Window {
userClick?: (userID?: string, groupID?: string) => void;
editRevoke?: (clientMsgID: string) => void;
screenshotPreview?: (results: string) => void;
// Qt WebChannel 相关
// qt 对象
qt: {
webChannelTransport: QWebChannel.Transport; // qt传递的对象
};
coreRef?: IQWebChannelCore; // 回调函数中传递的对象
// qtwebchannel.js 没有 types 结构,自行定义
// 直接挂载在 window 上的 QWebChannel
QWebChannel: typeof QWebChannel; // qt webchannel 核心
QObject?: typeof QWebChannel.QObject; // qt webchannel 基本对象结构
QWebChannelMessageTypes?: QWebChannel.MessageTypes; // qt webchannel 消息类型
}
}
第三步:关于初始化组件,在顶级路由增加逻辑勾子,此组件将使用在路由配置当中
import { Outlet } from "react-router-dom";
import { useQtWebChannel } from "@/hooks/useQtWebChannel";
export const MainContentWrap = () => {
useQtWebChannel();
return <Outlet />;
};
第四步:完成勾子逻辑
import { useEffect } from "react";
import { useQtStore } from "@/store/qtStore";
import { QtGroupItem, QtStore } from "@/store/type";
export function useQtWebChannel() {
// store 更新 qt 消息部分实现
const { updateGroupItems, setLoading, setError } = useQtStore((state: any) => ({
updateGroupItems: state.updateGroupItems,
setLoading: state.setLoading,
setError: state.setError,
}));
useEffect(() => {
// qt初始化实现
// qt开启9222端口,启用webview调试
const initQtWebChannel = () => {
if (typeof window !== "undefined" && !window.qt) {
setError("Qt 对象未获取到!");
return;
}
setLoading(true);
try {
// 确保 QWebChannel 可用
if (!window.QWebChannel && !window.qt.webChannelTransport) {
throw new Error("Qt WebChannel 初始化失败");
}
// 初始化 WebChannel
new window.QWebChannel(window.qt.webChannelTransport, (channel: any) => {
// 获取 Qt 注册的对象
window.coreRef = channel.objects.QtInitObject;
// 连接各种信号
if (window.coreRef) {
// 这里与 Qt 端核对 函数功能,在window.coreRef可以展示所有qt注册函数
console.log(window.coreRef)
// 在这里调用你的 updateGroupItems ;更新store逻辑
// 与Qt通信在这里初始化
window.coreRef.XXX((QtMsg) => {
// 获取qt消息
console.log(QtMsg)
})
// 触发qt消息,类似于激活websocket客户端,建立双向通信
setInterval(() => {
// 心跳函数
window.coreRef.SendSinglToQt()...
}, 500)
}
});
} catch (error) {
setError(error instanceof Error ? error.message : "Qt WebChannel 初始化失败");
console.error("QtWebChannel 初始化错误:", error);
} finally {
setLoading(false);
}
};
// 检查是否在浏览器环境中
if (typeof window !== "undefined") {
// 确保 DOM 已加载
if (document.readyState === "complete") {
initQtWebChannel();
} else {
window.addEventListener("load", initQtWebChannel);
return () => window.removeEventListener("load", initQtWebChannel);
}
}
// 清理函数
return () => {
// 清空qt资源
window.qt.webChannelTransport = null;
// 如果有需要断开连接信号,可以在这里处理
window.coreRef.XXX(()=>{
// 断开qt链接
})
};
}, [setLoading, setError]);
// 调用 Qt 方法的通用函数
const callQtMethod = (methodName: string, ...args: any[]) => {
return new Promise((resolve, reject) => {
if (!window.qt || !window.qt.webChannelTransport) {
reject(new Error("Qt WebChannel not initialized"));
return;
}
try {
// Qt 对象是全局的
const qtObject = window.coreRef; // 使用我们初始化的 core 对象
if (!qtObject || !qtObject[methodName]) {
reject(new Error(`Qt method "${methodName}" not found`));
return;
}
// 调用 Qt 方法
qtObject[methodName](...args, (result: any) => {
resolve(result);
});
} catch (error) {
reject(error);
}
});
};
return {
isLoading: useQtStore((state) => state.isLoading),
error: useQtStore((state) => state.error),
};
}
第五步:路由中引入组件,触发initWebChannel初始化函数
import { createHashRouter, Navigate } from "react-router-dom";
import { MainContentLayout } from "@/layout/MainContentLayout";
import { MainContentWrap } from "@/layout/MainContentWrap";
import GlobalErrorElement from "./GlobalErrorElement";
const router = createHashRouter([
{
path: "/",
element: <MainContentWrap />,
errorElement: <GlobalErrorElement />,
children: [
{
element: <MainContentLayout />,
children: [
{
async lazy() {
const { Xxx } = await import("@/pages/xxx");
return { Component: Xxx };
},
index: true,
},
... // 你其余的路由
],
},
],
},
]);
export default router;
End
4007

被折叠的 条评论
为什么被折叠?



