qt5.12为什么不支持nodejs的代码啊

qt5.12为什么不支持nodejs的代码啊,第1张

跨平台必须要在 java 这类载体上的吧,否则也只能是 xx IDE for windows 其次你是要 C/C++ 语言的 IDE,Linux/Unix/BSD/OSX 上面基本上都是基于 gdb 的前端界面(如 Kdevelop),至于 Windows 平台,

  在界面上拖入QAxWidget并指定控件为{8856F961-340A-11D0-A96B-00C04FD705A2},这个值可以通过OleViewexe查到然后通过IHTMLWindow2接口的execScript方法执行Java

  在界面上拖入QAxWidget,注意这里不建议直接在UI设计界面指定控件,否则可能引起QtCreator崩溃

  建议在代码中动态设置,如:

  ui->axWidget->setControl("ShellExplorer"); ui->axWidget->dynamicCall("Navigate(QString)", "C:/1html");当然,上面的"C:/1html"是我测试的页面

  这里的办法是通过IHTMLWindow2接口的execScript方法执行JavaScript函数。可惜的是这个方法不支持函数返回值

  #include <MsHTMLh> { QAxObject document = ui->axWidget->querySubObject("Document"); IHTMLDocument2 doc2; document->queryInterface(QUuid(IID_IHTMLDocument2), (void)&doc2); if (doc2) { IHTMLWindow2 win2 = nullptr; if (doc2->get_parentWindow(&win2) == S_OK) { BSTR s1 = SysAllocString(L"Test()"); BSTR s2 = SysAllocString(L"JavaScript"); VARIANT ret; win2->execScript(s1, s2, &ret); SysFreeString(s2); SysFreeString(s1); } } }

  JavaScript函数如下

  <script language="javascript" type="text/javascript"> function Test() { alert("你调用了全局函数Test"); } </script>

目前,web页面嵌入Qt框架方式:

Qt:系统、一级、二级菜单框架;底部消息栏。

Web:三级菜单子页面。

开发方式:在web环境下开发完成后,将单独页面嵌入到qt中,html、js等文件都作为资源加入到qt工程中。

1、html页面中引入webchannel库:

<script src="////lib/qwebchanneljs"></script>

<script src="////js/component/webchanneljs"></script>

其中,webchanneljs中,初始化了qt与web之间的通道,并定义qt与web之间的消息类型和内容。消息类型对应各个页面具体功能。新加的页面消息需要在该文件中添加。

2、Qt中相应子页面中加入web页面路径:

例如 epvl模型研判页面 JudgePoolqml:

以上步骤完成,就可以在Qt中看到web页面了。接下来需要注意的事项:

3、每个web页面下的初始化函数都必须在qt侧调用,因为初始化用到的一些如userinfo等信息需要Qt侧传入。并且在web页面初始化完成后调用。

(1)web页面中,加入页面初始化完成信号。

(2)Qt页面中,加入消息接收,并发送到web页面初始化消息。

(3)在webchanneljs中,加入web页面初始化函数。

4、遇到的问题:

(1)html中引入的js,如placecodejs等,都有初始化函数,凡是涉及到userinfo的都需要在qt侧调用。

(2)web中对文件名称大小写不区分,在Qt中严格区分。

(3)父页面d窗中是一个iframe的情况,iframe初始化问题解决方法:

iframe的路径不能在父页面静态加载,这样会导致iframe的js先于父页面的js加载,正常逻辑应该父页面的js先加载

需要在父页面定义一个方法来触发iframe的初始化方法

(4)页面跳转之后,需要调用跳转目的界面方法的问题:

1web端js需要发出跳转信号

举例:案事件库的案件详情界面中跳转至案件比对(case_libjs)

2qt端qml接收跳转信号,调用CommonFunjumpSystemPage方法,再向web端发信号调用目的界面的方法

注意: 目的界面有可能是初次打开,需要等目的界面初始化完成才能发调用web端方法(CaseLibqml)

3qt端目的界面需要定义初始化完成的信号,便于其他qt界面知道界面初始化完成:

(<u>compare_casejs</u>)

(<u>CompareCaseqm</u>l)

ActiveX技术虽然是一项古老的技术,但是却有着广泛的应用,支付宝的密码输入控件,各大银行的密码输入控件,网页聊天室中的截屏功能,网页播放器中的p2p播放甚至Flash,Silverlight等等,在IE中都表现为ActiveX。虽然C#也能开发"用于网页的com应用",能达到类似ActiveX的效果,但是有一个要命的问题是必须得安装几百M的net Framework框架,如果仅仅为了安全的输入一个密码,而要用户下载几百M的安装程序,这是很多人不能接受的,Delphi做为win32下的原生开发工具,能很好的支持微软各种"古老"的经典技术。(再做点小广告:delphi的kyrix版本还能编译跨平台的应用哦!) 

  ok,开工吧:

  开发工具:推荐用delphi 2010(d7也可以,不过添加属性,方法等过程要手动,稍微麻烦点) 

  1启用delphi2010-->File->New->Other-->Active Library

  2项目命名为MyActiveX

  3File-->Save All 全部保存

实际上这样就能编译了,不过只是空的dll

  4File-->New-->Other-->Active Form

  改名为MyForm

  将对应的单元文件,保存为UMyFormpas

  5打开MyAcitveXridl文件,切换到design视图,选中IMyForm接口,右击New-->Property

添加一个属性Msg

  将Msg属性的Type改为BSTR 即WideString类型

  完了之后,点击工具栏中的Refresh

Implementation(即上图中工具栏中圈起来的部分)--这一步很重要,点击之后,它将自动生成属性Msg对应的声明和实现代码模板

6打开UMyFormpas--即ActiveForm对应的单元,找到Set_Msg以及Get_Msg的实现部分,补充代码如下:

function TMyFormGet_Msg: WideString;

begin

    result:=_msg;

end;

procedure TMyFormSet_Msg(const Value: WideString);

begin

  _msg := value;

end;

  当然TMyForm的private部分,得先加一个私有成员 

type

  TMyForm = class(TActiveForm, IMyForm)

  private

    { Private declarations }

    _msg:WideString;

  这样我们就为即将生成的ActiveX控件,添加了一个字符串类型的属性Msg,下面来测试一下:

  7编译项目,会生成一个MyActiveXocx,在运行栏里输入

  regsvr32 C:\Users\jimmyyang\Desktop\Delphi_activex\MyActiveX\MyActiveXocx

  注:这里ocx的路径,请各位根据自己的实际路径修改

  这样就完成了ocx的注册。

  8放到html里测试一下:

<OBJECT ID='x' name='x' CLASSID='CLSID:52D17094-0687-4A2F-B2DB-30F3189AC659' align=center hspace=0 vspace=0 ></OBJECT>

<script type='text/JavaScript'>

var x = documentgetElementById("x");

alert(xMsg);

</script>

  关于CLSID在哪里查看,打开:MyActiveX_TLBpas文件,定位到下面这里:

const

  // TypeLibrary Major and minor versions

  MyActiveXMajorVersion = 1;

  MyActiveXMinorVersion = 0;

  LIBID_MyActiveX: TGUID = '{49138437-8265-4B1A-9EAE-D0F615D68464}';

  IID_IMyForm: TGUID = '{54A20855-29A3-4C92-85DE-A419DA457C7A}';

  DIID_IMyFormEvents: TGUID = '{60BBC967-E1E6-4E98-BAE5-776BFD06E9CC}';

  CLASS_MyForm: TGUID = '{52D17094-0687-4A2F-B2DB-30F3189AC659}';

其中 CLASS_MyForm: TGUID对应的就是ClassID

  运行后,除了d出一个空白的警告框,暂时看不到其它:)(可不就是这样么?Msg属性没给任何初始值,当然是空字符串,所以d出一个空的警告框是正常的)

  9我们再来添加一些控件和方法,以验证刚才设置的属性确实有效

  在MyForm上添加一个文件框,一个按钮

 

  按钮的事件如下:

procedure TMyFormButton1Click(Sender: TObject);

begin

  _msg:= selfEdit1Text;

end;

  即把文本框的值赋给属性Msg

  再继续定位到Set_Msg,略做修改

procedure TMyFormSet_Msg(const Value: WideString);

begin

  _msg := value;

  selfEdit1Text := _msg;

end;

  即设置Msg属性时,同时也把值显示在文本框里,以便等会儿我们好测试在js中给activeX属性赋值的效果

  ok了,再来测试一下,编译一下,如果通不过,请先运行

  regsvr32 C:\Users\jimmyyang\Desktop\Delphi_activex\MyActiveX\MyActiveXocx /u

  将刚才注册的ocx反注册,同时关掉浏览器,不然该ocx文件一直被占用,无法更新

  修改一下html的代码:

<OBJECT ID='x' name='x' CLASSID='CLSID:52D17094-0687-4A2F-B2DB-30F3189AC659' align=center hspace=0 vspace=0 ></OBJECT>

<hr />

<input type='button' value='显示Msg属性的值' onclick='ShowMsg()'/>

<input type='button' value='设置Msg属性的值' onclick='SetMsg()'/>

<script type='text/JavaScript'>

var x = documentgetElementById("x");

var ShowMsg = function(){

    alert(xMsg);

}

var SetMsg = function(){

    xMsg = 'js传过来的值';

}

</script>

1、使用WebBrowser控件,可以 *** 作网页中的元素、控件,调用网页的JS方法。 可以使用MFC集成WebBrowser。 QT中,有与WebBrowser类似的QWebEngineView控件。

2、网页录入信息的本质是,你再填写了信息之后,浏览器根据你的输入,将数据通过HTTP的POST方式发送到服务器。你若是不想手动录入,便按照既定的格式,自己用程序构造HTTP的POST请求,然后将其发送到服务器即可。 这里我肯定只能给出思路,具体的实现如果楼主还不清楚的话,建议楼主自己去学习一下web的工作方式、HTTP相关知识。 清楚了HTTP之后,c的网络相关直接用socket。若嫌麻烦便找个HTTP客户端库吧,建议使用curl。

海量点位标注的出现,是为了解决普通设备点超过几百个性能极速降低的问题,普通的marker标注由于采用的是对象的形式存在于地图中,数量越多,占用内存特别大,超过1000个点性能极其糟糕,哪怕是用点聚合,拖动地图的时候更是一卡卡,简称卡成屎,加载的时候也是慢成一坨屎,所以迫切需要一个其他的形式来支持成千上万的海量点,最好的方式就是绘制图形,精简掉很多属性,比如自定义图标、旋转角度、单击动画跳动等一堆特性,这些其实大部分时候是不需要的,在海量点的场景下,完全可以牺牲这些特性,然后采用最简单的绘制图形的形式来绘制海量点,提供最基础的一个功能就是识别单击了哪个点就行。

海量点位标注核心就是采用地图内置的js对象类PointCollection,传入点位的经纬度坐标集合,同时还可以统一设置点的颜色、点的大小、点的形状,通过addEventListener监听单击事件判断单击了哪个点,最后通过添加覆盖物的形式将一个海量点覆盖物添加到地图中。

尺寸参数:

形状参数:

很遗憾,QtWebkits在Qt56以上版本被淘汰了,对于这个接口良且和其他类例如QWebFrame完美结合的组件就这么没了,我只能表示惋惜。对于QtWebEngine新的组件,不得不承认它从Chromium继承过来的强大的性能,但接口上还不是很丰富,和其他类的交互也不是很完美,期待Qt能够对其进行进一步开发,我也会不断的升级Qt,尝试新的接口。

目前而言,QWebEngine有以下缺点:

MinGW版本的Qt不支持,即便是Qt56版本以上也是不支持的。仅仅支持MSVC版本。

接口暂时不丰富

无法和QWebFrame进行交互(使用了新的QWebChannel和QWebEnginePage组合进行交互)

基于我们的GPS定位项目,参考:[Qt开发北斗定位系统融合百度地图API及Qt程序打包发布] ,我们在该项目中使用的是Qt55版本,在嵌入的浏览器作为加载地图用的是QWebKits组件,我们将其升级使用QWebEngine进行加载地图,和HTML和JS进行交互。我们以此为例,进行简要的介绍。

2 两者的UI上面的区别

你刚刚升级到Qt56版本可能在UI设计界面时候在组件中找不到QWebEngineView这个组件,无法从这里拖拽这个组件到你的UI界面上。我查阅了很多资料,看到别人经常使用 ui->webEngineview->这样,我甚至怀疑是否因为安装了其他版本的Qt影响到了我,我卸载了包含56版本的所有Qt,又重新安装了一遍,但是再重启软件后,依然没有发现QWebEngineView这个鬼东西。在Qt55中你也能发现有这样的组件QWebView,如图1所示:

QWebView组件可以通过QWebFrame来进行HTML和JS的通信,如果过渡到QWebEngineView,要是没有这个UI组件的话,我如何把浏览器嵌入到软件界面,实现网页和软件的混合编程呢。根据官方提供的一个例子中,cookiebrowser中找到了答案,这也是官方给的例子中,唯一一个嵌入到网页中的!(不得不说,Qt给的例子很模糊很差!) 经过研究, QWebEngineView使用widget组件,拖拉出来是一个透明的组件,对着组件按右键->promote to ->选择QWebEngineView,如图2,完成 *** 作。

有了QWebEngineView这个UI组件,我们可以在程序中调用其成员、方法和函数完成 *** 作了。

3 使用方法区别

在使用方法上有很大的区别,可以说是两个完全不同理念的东西,这里为了更通俗易懂,就不粘贴API文档中函数解释,就用最常用的!

#include <QtWebEngineWidgets>   // 基本组件#include <QWebEnginePage>       // HTML页面#include <QWebChannel>          // C++和JS/HTML双向通信,代替了已淘汰的QtWebFrame的功能

在我们的项目中一开始就要引入这样的组件,但在我们的项目中,没有频繁用到与JS的互相交互,所以这里暂时没有关于QWebChannel的使用方法,只留下这个接口。

以下为区别:

在WebKits中的初始化:

QUrl url(strMapPath);       // strMapPath为QString类,是你html文件的路径ui->webView->load(url);

ui->webView->setContentsMargins(0,0,0,0);

ui->webView->setTextSizeMultiplier(1);//设置网页字体大小connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),            this, SLOT(slotPopulateJavaScriptWindowObject()));

我们会使用load方法加载html所在的界面,使用QWebFrame类的mainFrame()中的SIGNAL和槽函数

void Widget::slotPopulateJavaScriptWindowObject()

{

   ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("ReinforcePC", this);

}

进行响应。参考文献1:《javascript调用qt》,可以解释这个槽函数的重要性。

在WebEngine中的初始化:

QWebEnginePage page = new QWebEnginePage(this);  // 定义一个page作为页面管理QWebChannel channel = new QWebChannel(this);     // 定义一个channel作为和JS或HTML交互page->load(strMapPath);                         // page上加载html路径page->setWebChannel(channel);                   // 把channel配置到page上,让channel作为其信使ui->webEngine->setPage(page);                   // 建立page和UI上的webEngine的联系

如果你的 初始化程序写到这里,当你运行程序的时候,无论是webKits里的WebView还是新版的webEngineView,你的UI界面上的那个组件区域就会显示那个html文件了。

到此,我们完成了两者的初始化。

WebKits组件中的运行JS:

我们以按钮的槽函数为例,当点击按钮时,会向JS发送命令,运行JS脚本,我们这里发送的是将显示变为卫星图的JS命令:

void Widget::on_pushButtonStreetMap_clicked()

{    QWebFrame frame = ui->webView->page()->mainFrame(); // 定义一个QWebFrame负责交互

   QString cmd = QString("showStreetMap()"); // JS的命令

   frame->evaluateJavaScript(cmd);           // 使用frame下的命令运行该命令}

从这个例子中我们也可以看到,QWebFrame是JS交互的关键。

WebEngine组件中的运行JS:

还是以该槽函数为例:

void Widget::on_pushButtonSatelliteMap_clicked()

{    QString cmd = "showSatelliteMap()";

   ui->webEngine->page()->runJavaScript(cmd);      // 直接page()下就可以运行}

在JS单向通信中十分简单,也不需要使用QWebChannel信使,但该方法runJavaScript()无法在构造函数中使用,原因不明。也可以这样使用:

connect(ui->webEngine,&QWebEngineView::loadFinished,[=](int){

            ui->webEngine->page()->runJavaScript(cmd1);

第二个参数SIGNAL位置的,只能使用这样的方式调用,如果使用SIGNAL(loadFinished),报错。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/11670218.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-17
下一篇2023-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存