0


qt和vue交互

1、首先在vue项目中引入qwebchannel

/****************************************************************************
 **
 ** Copyright (C) 2016 The Qt Company Ltd.
 ** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected], author Milian Wolff <[email protected]>
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtWebChannel module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
 ** Software or, alternatively, in accordance with the terms contained in
 ** a written agreement between you and The Qt Company. For licensing terms
 ** and conditions see https://www.qt.io/terms-conditions. For further
 ** information use the contact form at https://www.qt.io/contact-us.
 **
 ** GNU Lesser General Public License Usage
 ** Alternatively, this file may be used under the terms of the GNU Lesser
 ** General Public License version 3 as published by the Free Software
 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
 ** packaging of this file. Please review the following information to
 ** ensure the GNU Lesser General Public License version 3 requirements
 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 **
 ** GNU General Public License Usage
 ** Alternatively, this file may be used under the terms of the GNU
 ** General Public License version 2.0 or (at your option) the GNU General
 ** Public license version 3 or any later version approved by the KDE Free
 ** Qt Foundation. The licenses are as published by the Free Software
 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 ** included in the packaging of this file. Please review the following
 ** information to ensure the GNU General Public License requirements will
 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 ** https://www.gnu.org/licenses/gpl-3.0.html.
 **
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/"use strict";var QWebChannelMessageTypes ={signal:1,propertyUpdate:2,init:3,idle:4,debug:5,invokeMethod:6,connectToSignal:7,disconnectFromSignal:8,setProperty:9,response:10,};exportvarQWebChannel=function(transport, initCallback){if(typeof transport !=="object"||typeof transport.send !=="function"){
        console.error("The QWebChannel expects a transport object with a send function and onmessage callback property."+" Given is: transport: "+typeof(transport)+", transport.send: "+typeof(transport.send));return;}var channel =this;this.transport = transport;this.send=function(data){if(typeof(data)!=="string"){
            data =JSON.stringify(data);}
        channel.transport.send(data);}this.transport.onmessage=function(message){var data = message.data;if(typeof data ==="string"){
            data =JSON.parse(data);}switch(data.type){case QWebChannelMessageTypes.signal:
                channel.handleSignal(data);break;case QWebChannelMessageTypes.response:
                channel.handleResponse(data);break;case QWebChannelMessageTypes.propertyUpdate:
                channel.handlePropertyUpdate(data);break;default:
                console.error("invalid message received:", message.data);break;}}this.execCallbacks ={};this.execId =0;this.exec=function(data, callback){if(!callback){// if no callback is given, send directly
            channel.send(data);return;}if(channel.execId === Number.MAX_VALUE){// wrap
            channel.execId = Number.MIN_VALUE;}if(data.hasOwnProperty("id")){
            console.error("Cannot exec message with property id: "+JSON.stringify(data));return;}
        data.id = channel.execId++;
        channel.execCallbacks[data.id]= callback;
        channel.send(data);};this.objects ={};this.handleSignal=function(message){var object = channel.objects[message.object];if(object){
            object.signalEmitted(message.signal, message.args);}else{
            console.warn("Unhandled signal: "+ message.object +"::"+ message.signal);}}this.handleResponse=function(message){if(!message.hasOwnProperty("id")){
            console.error("Invalid response message received: ",JSON.stringify(message));return;}
        channel.execCallbacks[message.id](message.data);delete channel.execCallbacks[message.id];}this.handlePropertyUpdate=function(message){
        message.data.forEach(data=>{var object = channel.objects[data.object];if(object){
                object.propertyUpdate(data.signals, data.properties);}else{
                console.warn("Unhandled property update: "+ data.object +"::"+ data.signal);}});
        channel.exec({type: QWebChannelMessageTypes.idle
        });}this.debug=function(message){
        channel.send({type: QWebChannelMessageTypes.debug,data: message
        });};

    channel.exec({type: QWebChannelMessageTypes.init
    },function(data){for(const objectName of Object.keys(data)){newQObject(objectName, data[objectName], channel);}// now unwrap properties, which might reference other registered objectsfor(const objectName of Object.keys(channel.objects)){
            channel.objects[objectName].unwrapProperties();}if(initCallback){initCallback(channel);}
        channel.exec({type: QWebChannelMessageTypes.idle
        });});};functionQObject(name, data, webChannel){this.__id__ = name;
    webChannel.objects[name]=this;// List of callbacks that get invoked upon signal emissionthis.__objectSignals__ ={};// Cache of all properties, updated when a notify signal is emittedthis.__propertyCache__ ={};var object =this;// ----------------------------------------------------------------------this.unwrapQObject=function(response){if(response instanceofArray){// support list of objectsreturn response.map(qobj=> object.unwrapQObject(qobj))}if(!(response instanceofObject))return response;if(!response["__QObject*__"]|| response.id ===undefined){var jObj ={};for(const propName of Object.keys(response)){
                jObj[propName]= object.unwrapQObject(response[propName]);}return jObj;}var objectId = response.id;if(webChannel.objects[objectId])return webChannel.objects[objectId];if(!response.data){
            console.error("Cannot unwrap unknown QObject "+ objectId +" without data.");return;}var qObject =newQObject(objectId, response.data, webChannel);
        qObject.destroyed.connect(function(){if(webChannel.objects[objectId]=== qObject){delete webChannel.objects[objectId];// reset the now deleted QObject to an empty {} object// just assigning {} though would not have the desired effect, but the// below also ensures all external references will see the empty map// NOTE: this detour is necessary to workaround QTBUG-40021
                Object.keys(qObject).forEach(name=>delete qObject[name]);}});// here we are already initialized, and thus must directly unwrap the properties
        qObject.unwrapProperties();return qObject;}this.unwrapProperties=function(){for(const propertyIdx of Object.keys(object.__propertyCache__)){
            object.__propertyCache__[propertyIdx]= object.unwrapQObject(object.__propertyCache__[propertyIdx]);}}functionaddSignal(signalData, isPropertyNotifySignal){var signalName = signalData[0];var signalIndex = signalData[1];
        object[signalName]={connect:function(callback){if(typeof(callback)!=="function"){
                    console.error("Bad callback given to connect to signal "+ signalName);return;}

                object.__objectSignals__[signalIndex]= object.__objectSignals__[signalIndex]||[];
                object.__objectSignals__[signalIndex].push(callback);// only required for "pure" signals, handled separately for properties in propertyUpdateif(isPropertyNotifySignal)return;// also note that we always get notified about the destroyed signalif(signalName ==="destroyed"|| signalName ==="destroyed()"|| signalName ==="destroyed(QObject*)")return;// and otherwise we only need to be connected only onceif(object.__objectSignals__[signalIndex].length ==1){
                    webChannel.exec({type: QWebChannelMessageTypes.connectToSignal,object: object.__id__,signal: signalIndex
                    });}},disconnect:function(callback){if(typeof(callback)!=="function"){
                    console.error("Bad callback given to disconnect from signal "+ signalName);return;}
                object.__objectSignals__[signalIndex]= object.__objectSignals__[signalIndex]||[];var idx = object.__objectSignals__[signalIndex].indexOf(callback);if(idx ===-1){
                    console.error("Cannot find connection of signal "+ signalName +" to "+ callback.name);return;}
                object.__objectSignals__[signalIndex].splice(idx,1);if(!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length ===0){// only required for "pure" signals, handled separately for properties in propertyUpdate
                    webChannel.exec({type: QWebChannelMessageTypes.disconnectFromSignal,object: object.__id__,signal: signalIndex
                    });}}};}/**
     * Invokes all callbacks for the given signalname. Also works for property notify callbacks.
     */functioninvokeSignalCallbacks(signalName, signalArgs){var connections = object.__objectSignals__[signalName];if(connections){
            connections.forEach(function(callback){callback.apply(callback, signalArgs);});}}this.propertyUpdate=function(signals, propertyMap){// update property cachefor(const propertyIndex of Object.keys(propertyMap)){var propertyValue = propertyMap[propertyIndex];
            object.__propertyCache__[propertyIndex]=this.unwrapQObject(propertyValue);}for(const signalName of Object.keys(signals)){// Invoke all callbacks, as signalEmitted() does not. This ensures the// property cache is updated before the callbacks are invoked.invokeSignalCallbacks(signalName, signals[signalName]);}}this.signalEmitted=function(signalName, signalArgs){invokeSignalCallbacks(signalName,this.unwrapQObject(signalArgs));}functionaddMethod(methodData){var methodName = methodData[0];var methodIdx = methodData[1];// Fully specified methods are invoked by id, others by name for host-side overload resolutionvar invokedMethod = methodName[methodName.length -1]===')'? methodIdx : methodName

        object[methodName]=function(){var args =[];var callback;var errCallback;for(var i =0; i < arguments.length;++i){var argument = arguments[i];if(typeof argument ==="function")
                    callback = argument;elseif(argument instanceofQObject&& webChannel.objects[argument.__id__]!==undefined)
                    args.push({"id": argument.__id__
                    });else
                    args.push(argument);}var result;// during test, webChannel.exec synchronously calls the callback// therefore, the promise must be constucted before calling// webChannel.exec to ensure the callback is set upif(!callback &&(typeof(Promise)==='function')){
                result =newPromise(function(resolve, reject){
                    callback = resolve;
                    errCallback = reject;});}

            webChannel.exec({"type": QWebChannelMessageTypes.invokeMethod,"object": object.__id__,"method": invokedMethod,"args": args
            },function(response){if(response !==undefined){var result = object.unwrapQObject(response);if(callback){(callback)(result);}}elseif(errCallback){(errCallback)();}});return result;};}functionbindGetterSetter(propertyInfo){var propertyIndex = propertyInfo[0];var propertyName = propertyInfo[1];var notifySignalData = propertyInfo[2];// initialize property cache with current value// NOTE: if this is an object, it is not directly unwrapped as it might// reference other QObject that we do not know yet
        object.__propertyCache__[propertyIndex]= propertyInfo[3];if(notifySignalData){if(notifySignalData[0]===1){// signal name is optimized away, reconstruct the actual name
                notifySignalData[0]= propertyName +"Changed";}addSignal(notifySignalData,true);}

        Object.defineProperty(object, propertyName,{configurable:true,get:function(){var propertyValue = object.__propertyCache__[propertyIndex];if(propertyValue ===undefined){// This shouldn't happen
                    console.warn("Undefined value in property cache for property \""+ propertyName +"\" in object "+ object.__id__);}return propertyValue;},set:function(value){if(value ===undefined){
                    console.warn("Property setter for "+ propertyName +" called with undefined value!");return;}
                object.__propertyCache__[propertyIndex]= value;var valueToSend = value;if(valueToSend instanceofQObject&& webChannel.objects[valueToSend.__id__]!==undefined)
                    valueToSend ={"id": valueToSend.__id__
                    };
                webChannel.exec({"type": QWebChannelMessageTypes.setProperty,"object": object.__id__,"property": propertyIndex,"value": valueToSend
                });}});}// ----------------------------------------------------------------------

    data.methods.forEach(addMethod);

    data.properties.forEach(bindGetterSetter);

    data.signals.forEach(function(signal){addSignal(signal,false);});

    Object.assign(object, data.enums);}//required for use with nodejs// if (typeof module === 'object') {//     module.exports = {//         QWebChannel: QWebChannel//     };// }

2、在main.js引入

import{ createApp }from'vue'import App from'./App.vue'import router from'./router'import{QWebChannel}from'../public/js/qwebchannel.js'import store from'./store'exportvar qtWebChannel =null;newQWebChannel(qt.webChannelTransport,(channel)=>{
    qtWebChannel = channel.objects.qtJSBridge;});createApp(App).use(store).use(router).mount('#app')

3、在页面中使用

<script setup name="index">import{ qtWebChannel }from"@/main.js";import{ getCurrentInstance, onMounted, reactive, ref }from"vue";onMounted(()=>{let msgType ="loadDataReq";let obj ={ msgType };setTimeout(()=>{
    qtWebChannel.sendMessageToJS.connect((response)=>{let dataQt ={};if(response){
        dataQt =JSON.parse(response);}})
     qtWebChannel.sendMessageToQt(JSON.stringify(obj));},1000);});</script>

4、router配置

import{ createRouter, createWebHashHistory }from'vue-router'const routes =[{path:'/',name:'index',component:()=>import('@/views/index/Index')},]const router =createRouter({//此处只能用hash模式,不然<router-view>里面的东西不能加载history:createWebHashHistory(),
  routes
})exportdefault router

5、打包后将资源文件在QT项目中用qrc引入

6、效果图

在这里插入图片描述

注意:
history只能用hash模式,不然里面的东西不能加载

标签: qt vue.js 交互

本文转载自: https://blog.csdn.net/qq_41994014/article/details/131727603
版权归原作者 南有嘉念 所有, 如有侵权,请联系我们删除。

“qt和vue交互”的评论:

还没有评论