Qt——Javascript/Qt交互、脚本化

news2025/7/19 7:07:49

Qt提供了对Javascript的良好支持, 如果查阅过文档你就知道Qt有两个不同的Js封装引擎:

  • QScriptEngine

  • QJSEngine

QScriptEngine出现的比较早(自Qt4.3始),基于WebKit的JavaScriptCore引擎,提供的api相对来说比较丰富,但是已经被官方标注为deprecated;QJSEngine则是从Qt5.0开始提供,基于谷歌的V8引擎,是官方建议使用的版本。至于为什么QScriptEngine会被Qt废弃,各种原因就比较复杂了,有兴趣的朋友可以看这个链接,我这里简要概括讲一下Qt js模块的实现历史及原因:

  1. QScriptEngine---使用自建的js引擎:功能落后、运行非常慢。
  2. QScriptEngine---使用JavaScriptCore引擎(WebKit的主引擎):由此封装提供的JS API暴露了实现细节。由于设计使用方式的不同一些原有函数无法实现(例如QScriptContext)。JavaScriptCore变化太大,没有一个稳定的API来供QtScript实现想要的功能,每一次引擎的变化都需要QtScript模块内部进行大的调整。
  3. QScriptEngine---使用V8引擎:V8对外提供的API稳定,可嵌入到程序中;但是V8与JavaScriptCore内部细节不同,QtScript API的某些概念无法自然映射到V8上,用V8实现相同性能的旧接口需要相当大的投入,然而QML团队无法接受这样的投入花费。
  4. QJSEngine-------使用V8引擎。

1. QScriptEngine VS QJSEngine

从两个主要的引擎类上来说,相比QScriptEngine,虽然QJSEngine出来的迟,但是核心的功能(加粗)也是支持的,仅在其他一些小功能上有所欠缺(未加粗):

  • 执行脚本字符串。
  • 引擎全局变量配置。
  • 异常处理。
  • Js对象创建
  • Qt类与Js的交互集成。
  • Js扩展。
  • 自定义C++类(非Qt内建)。
  • C++函数与Js的交互集成。
  • Long-running脚本优化处理。
  • 调试跟踪。

但是毕竟对JavaScriptCore引擎的封装比较成熟,从QScriptEngine衍生出的技术支持肯定是比较丰富,使用也较为方便。例如QtScript模块同时包含QScriptClassPropertyIterator类来提供java风格的属性遍历功能、QScriptContext类来提供上下文信息,等等。但是随着Qt新版本的发布,QJsEngine肯定是越来越成熟的。需要注意的是,这两个应该都不能与Qt的Web模块交互使用(亲测QJSEngine与QWebEngineView交互无效),毕竟都分成了两个不同的模块。

2. QJSEngine介绍

这里我们简单学习QJSEngine,一如既往,我们通过一个小例子来学习当前js引擎提供的主要功能, 实际上使用非常简单。

2.1 执行脚本

QJSValue QJSEngine::evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1)

我们只需要把包含js代码的字符串传给QJSEngine::evaluate()这个函数,就可以直接执行该js代码。该函数的后两个参数是可选的文件名和行号,会在js出错的时候包含在出错信息里。示例程序中当用户点击执行按钮,我们直接就执行用户输入的js代码:

void MainWindow::on_buttonEvaluateJs_clicked(bool)
{
    ui->lineEditJsResult->setText(
                m_jsEngine.evaluate(ui->lineEditEvaluateJs->text()).toString());
    ui->lineEditJsResult->setEnabled(ui->buttonEvaluateJs->isEnabled());
}

2.2 配置引擎的全局变量(C++/Js交互)

QJSValue QJSEngine::globalObject() const
QJSValue QJSEngine::newObject()
void QJSValue::setProperty(const QString &name, const QJSValue &value)

通过globalObject()函数我们获得Js引擎的全局变量,这个变量是一个QJSValue,是Qt对Js数据类型的一个封装,基本上支持所有Js对象的操作。例如,我们可以判断两个QJSValue是否相等、是否严格相等、设置属性、设置原型等。全局对象就是一个可以在Js代码中直接使用的Js变量,通常我们做的就是在C++代码里设置全局变量的属性,然后在Js中直接使用。

newObject()函数用来新建一个Js对象,示例中我们在新建的Js对象上分别设置3个属性(setProperty())为用户输入的左操作数、右操作数和运算符,然后把这个对象设置为全局对象的一个属性,接着我们在Js代码中直接调用这3个属性来进行计算:

void MainWindow::on_buttonEvaluatePropertyCalculateResult_clicked(bool)
{
    auto jsObject = m_jsEngine.newObject();
    jsObject.setProperty("leftOperand", ui->lineEditPropertyLeft->text());
    jsObject.setProperty("rightOperand", ui->lineEditPropertyRight->text());
    m_jsEngine.globalObject().setProperty("cppObject", jsObject);

    ui->lineEditEvaluatePropertyResult->setText(m_jsEngine.evaluate(
        "cppObject.leftOperand" +
        ui->lineEditPropertyOperator->text() +
        "cppObject.rightOperand").toString());
    ui->lineEditEvaluatePropertyResult->setEnabled(
        ui->buttonEvaluatePropertyCalculateResult->isEnabled());
}

2.3 Qt/Js交互(脚本化)

QJSValue newQObject(QObject *object)

Signals and slots, properties and children of object are available as properties of the created QJSValue.

通过newQObject()这个函数,我们可以将Qt类封装成Js对象,集成到Js引擎中。Qt类的信号槽属性子对象可以在Js中通过属性来使用,Qt提供强大的本地功能支持,Js提供灵活的使用方式,想想就很激动。我们可以借此在Js中操控导出的Qt对象、更改界面外观、实现程序功能的脚本化。

示例中我们导出街面上的一个QPushButton,把它设置为Js引擎全局对象的一个属性:

m_jsEngine.globalObject().setProperty("cppButton", m_jsEngine.newQObject(ui->buttonChangeInJs));

当用户点击这个按钮的时候,我们读取本地的Js文件到QString中并执行这段代码,该Js代码会调用setStyleSheet()函数(注意这是一个slot)来更改这个按钮的外观样式:

void MainWindow::on_buttonChangeInJs_clicked(bool)
{
    QFile jsFile(":/js/demo.js");
    if (jsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        auto jsStr = QString::fromStdString(jsFile.readAll().toStdString());
        auto jsResult = m_jsEngine.evaluate(jsStr);

        if (jsResult.isError())
            ui->buttonChangeInJs->setText(jsResult.toString());
    }
}

function func() {
    cppButton.setStyleSheet('QPushButton { background-color: qlineargradient(\
                                                x0:0, y0:0, x1:1, y1:1, \
                                                stop: 0.0 #111111,\
                                                stop: 0.2 #222222,\
                                                stop: 0.4 #444444,\
                                                stop: 0.6 #888888,\
                                                stop: 0.8 #aaaaaa,\
                                                stop: 1.0 #ffffff);\
                                        color:white;}\
                            QPushButton:hover { border:2px solid blue;\
                                                padding:1ex; }\
                            QPushButton:pressed { background-color: qlineargradient(\
                                                x0:0, y0:0, x1:1, y1:1, \
                                                stop: 0.0 #ff1111,\
                                                stop: 0.2 #22ff22,\
                                                stop: 0.4 #4444ff,\
                                                stop: 0.6 #88ee88,\
                                                stop: 0.8 #aaeeaa,\
                                                stop: 1.0 #ffffff); }')
    cppButton.text = 'Changed in JS'
}
func()

3. 运行结果

编辑切换为居中

添加图片注释,

编辑切换为居中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/369238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(一维、二维)数组传参,(一级、二级)指针传参【含样例分析,新手易懂】

目录数组传参一维数组传参二维数组传参指针传参一级指针传参二级指针传参我们在写代码的时候难免要把数组或者指针传给函数&#xff0c;那函数的参数该如何设计呢&#xff1f; 数组传参 一维数组传参 我们首先来看下面代码的几个例子&#xff1a; #include <stdio.h>…

优化长尾关键词有什么好处?在线长尾关键词挖掘

​想知道为什么要使用长尾关键词&#xff1f; 好吧&#xff0c;它们可以帮助你轻松找到合适的受众。 ​ 1.获得更高的转化率 长尾关键词对于搜索特定信息更有用。使用长尾关键词时通常会获得更高的转化率&#xff0c;因为内容与受众的需求更相关。 举个例子&#xff1a;你正…

3年测试拿8K,被校招来的实习生反超薪资,其实你在假装努力

最近朋友给我分享了一个他公司发生的事 大概的内容呢&#xff1a;公司一位工作3年的测试工资还没有新人高&#xff0c;对此怨气不小&#xff0c;她来公司辛辛苦苦三年&#xff0c;三年内迟到次数都不超过5次&#xff0c;每天都是按时上下班&#xff0c;工作也按量完成&#xf…

【华为OD机试模拟题】用 C++ 实现 - 最低位排序(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…

结构效度分析流程

结构效度分析流程如下图 一、结构效度的意义 效度分析在学术研究中非常常见&#xff0c;结构效度是为了分析“从量表获得的结果与设计该量表时所假定的理论之间的符合程度”。简单来讲&#xff0c;在研究者设计量表之初&#xff0c;一般会预设好几个维度&#xff0c;在经过因子…

docker搭建MySQL集群(1主1从)

1.创建挂载路径及配置文件my.cnf&#xff0c;挂载mysql的数据、配置、日志 /usr/mydata/mysql/conf/s1 /usr/mydata/mysql/conf/m1my.cnf先只写server-id,保证主从不同 2.拉取MySQL镜像&#xff0c;启动两个实例 docker run -p 3316:3306 --name mysql-m1 -v /usr/mydata/m…

识别密文加密类型

离线密码破解&#xff1a;离线不会触发密码锁定机制不会产生大量登录失败日志引起管理员注意HASH识别工具&#xff08;识别哈希类型&#xff09;&#xff1a;hash-identifierHashid yara规则匹配文件得到特定加密算法一、hash-identifierKali Linux提供工具hash-identifier来识…

LabVIEW如何调用.m脚本LabVIEW调用MATLAB

LabVIEW如何调用.m脚本LabVIEW调用MATLAB有一个用MATLAB编写的脚本&#xff0c;想知道从LabVIEW调用它的方法&#xff0c;以及哪一个是最快的。解决方法有几种方法可以在LabVIEW中调用.m脚本。LabVIEW中的MATLABScript Node使用ActiveX调用MATLAB运行时系统。注意&#xff1a;不…

Nginx 02篇——Nginx基本配置与参数说明篇

Nginx 02篇——Nginx基本配置与参数说明篇前言-默认配置文件1. 前言——关于nginx1.1 关于nginx1. 2 Nginx 01篇——Nginx安装2. Nginx 配置文件结构2.1 Nginx 安装后的默认文件2.2 Nginx 的三大组成部分3. 配置参说明-1——整个配置3.1 配置说明3.2 参考4. 配置说明-2—详细说…

增量更新jar包的方法

由于现在绝大多数服务都采用spring boot,且在打包时一般选择全量包的形式,因此在服务依赖比较多的情况下,更新/添加其中的一个文件时,会造成很大的麻烦,比如一个服务打完包后,jar文件的体积可能在200M左右,因此在网络条件不好的情况下&#xff0c;频繁更新服务包还是比较麻烦的…

http/HTTPS相关的一些知识

2、http和https HTTP&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。HTTP 是应用层协议&#xff0c;它以 TCP&#xff08;传输层&#xff09;作为底层协议&#xff0c;默认端口为 80。 http的通信过程&#xff1a;服务器在80端口等待客户的请…

联想Thinkpad X1 Carbon (7th Gen)电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。硬件型号驱动情况主板Thinkpad X1 Carbon处理器Intel Core i5-10210U (formerly Comet Lake)已驱动内存8GB DDR3 (or something like that)已驱动硬盘WDC PC SN730 SDBQNTY-256G-1001已驱动显卡Intel UHD 620Nvidia GeForce…

【AcWing-Python-785】快速排序

题目&#xff1a;https://www.acwing.com/problem/content/description/787/对应视频讲解&#xff1a;https://www.acwing.com/video/227/题目描述注意本题数据已加强。快速排序过程中&#xff0c;如果每次取区间起点或者终点作为分界点&#xff0c;则会超时。分界点换成随机值…

自动化测试工具airtest之上传文件或图片(web自动化上传图片)

web自动化测试图片上传的方法&#xff1a; 第一种为当具有input标签时&#xff0c;如&#xff1a; <input type"file" name"file" multiple"multiple"> 这类可以通过selenium中的send_keys()上传 直接实现&#xff1a; driver.find_eleme…

成功“拿捏”金三银四!汇总Java面试突击班后的面试小册

最近很多同学已经开始进行今年的面试了&#xff0c;好多同学说&#xff0c;想要今年最新版的Java面试突击班的内容话说回来&#xff0c;今天给大家分享的就是咱们面试突击班的文字PDF版本&#xff0c;下面是文字版的分享大家可以详细往下看&#xff01;由于文章的篇幅有限&…

常见web安全漏洞-暴力破解,xss,SQL注入,csrf

1&#xff0c;暴力破解 原理&#xff1a; 使用大量的认证信息在认证接口进行登录认证&#xff0c;知道正确为止。为提高效率一般使用带有字典的工具自动化操作 基于表单的暴力破解 --- 若用户没有安全认证&#xff0c;直接进行抓包破解。 验证码绕过 on server ---验证码校验在…

局域网下mac与win通过ssh互联(端口映射)

目录一、前置条件ip查看关闭防火墙二、win端ssh连接mac三、mac端ssh连接win四、mac端ssh连接win上的linux虚拟机此文章欢迎访问我的个人博客&#xff1a;https://qiandao.space/archives/portmapping mac端ssh连接win mac端ssh连接win上的linux虚拟机 win端ssh连接mac 日常开发…

【知识蒸馏】知识蒸馏(Knowledge Distillation)技术详解

参考论文&#xff1a;Knowledge Distillation: A Survey 1.前言 ​ 近年来&#xff0c;深度学习在学术界和工业界取得了巨大的成功&#xff0c;根本原因在于其可拓展性和编码大规模数据的能力。但是&#xff0c;深度学习的主要挑战在于&#xff0c;受限制于资源容量&#xff0…

Unity——使用铰链关节制作悬挂物体效果

目的在场景中创建一个悬挂的物体&#xff0c;是把多个模型悬挂在一起可以自由摇摆&#xff0c;类似链条的效果效果图前言什么是铰链关节&#xff1f;铰链关节 将两个刚体&#xff08;Rigid body&#xff09;组会在一起&#xff0c;从而将其约束为如同通过铰链连接一样进行移动。…

JavaSE基础部分总结

JavaSe基础部分 文章目录JavaSe基础部分1.命名规范2.基本的数据类型3.方法3.1方法的基本格式3.2 方法的分类3.3 方法的注释4.数组4.1 数组的命名格式4.2 数组中存在的址交换的操作4.3数组Arrays常用的方法1. Arrays.asList(数组作为参数或者数据作为参数)&#xff1a;2.Arrays.…