QT中使用WebKit中的一些问题
1. 基本的使用方法
1.1 加入项目依赖
(1)在pro文件中加入QT += webkit
或在cmakeList.txt中加入(本人未试过):
find_package(Qt4 COMPONENTS Widgets WebKit REQUIRED)
target_link_libraries(webEngineTest PRIVATE Qt4::Widgets Qt4::WebKit)
(2)生成实例
在mainWindow.h中加入
#include <QWebView>
QWebView* webView;
在mainWindow. cpp构造函数中加入:
webView = new QWebView(this); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(webView); QWidget* widget = new QWidget(); widget->setLayout(layout); setCentralWidget(widget); //webView->resize(this->size()); //webView->move(0, 0); QString fpath = QCoreApplication::applicationDirPath(); fpath.append("/test1.html"); QUrl url = QUrl::fromUserInput(fpath); webView->load(url); webView->show();
2. QT交互类的槽定义
定义新类需要注意
(1)需要由js调用的函数必须定义为槽函数,不返回值(试验中,返回值失败)。
(2)槽函数的参数不要采用引用方式,采用值传递(试验中,引用方式调用失败)。
//env_scenario.h
#ifndef ENV_SCENARIO_H #define ENV_SCENARIO_H #include <QObject> #include <QWebView> class Env_scenario : public QObject { Q_OBJECT public: explicit Env_scenario(QWebView* webView, QObject *parent = NULL); public slots: //***!!!与java绑定时,不能用引用传递参数,否则不能使用 //***!!!槽函数不能返回值,否则出现异常 void setMyItemText(QString id); void secondSlot(QString txt); private: QWebView* m_pWebView; }; #endif // ENV_SCENARIO_H
//env_scenario.cpp
#include "env_scenario.h"
#include <QDebug> #include <QMessageBox> Env_scenario::Env_scenario(QWebView* webView, QObject *parent) :QObject(parent), m_pWebView(webView) { } void Env_scenario::setMyItemText(QString id) { QMessageBox::information(NULL, "in Env_scenario::setMyItemText", id); qDebug() << id << endl; } void Env_scenario::secondSlot(QString txt) { QMessageBox::information(NULL, "in Env_scenario::secondSlot", txt); qDebug() << txt << endl; }
3. 注册交互类对象
在主程序中生成交互类实例后,通过webView进行注册
envSce = new Env_scenario(webView, this); opoSce = new Opo_scenario(webView, this); webView->page()->mainFrame()->addToJavaScriptWindowObject("Evnitem", envSce); //***!!!看来不能同时注册两个对象 //webView->page()->mainFrame()->addToJavaScriptWindowObject("Opoitem", opoSce);
需要注意的是:
(1)一个webView只能注册一个交互类对象(试验过两个,失败)
(2)如果出现错误提示:unable using incomplete class,需要加入#include<QWebForm>
4.创建html文档
(1)当主程序注册了交互实体后,本实例就成为html文件中window的一个成员,可以用window."实例名"."函数名"调用其函数
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>scenario edit</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Language" content="Chinese"> <link rel="stylesheet" type="text/css" href="./element-ui/lib/theme-chalk/index.css"> <script language="javascript"> function setEvnItem() { alert("call Evnitem"); window.Evnitem.setMyItemText("call Evnitem"); } function setOpoItem() { //alert("call Opoitem"); window.Evnitem.secondSlot("call secondSlot"); } function setName(name) { alert(name); document.getElementById(name).innerHTML = name; } </script> </head> <body> <div id="app"> <h1>这是WebKit的一个应用</h1> <button onclick="SetEvnItem()">setEvnItem input</button> <br /><br /> <button onclick="setOpoItem()">setOpoItem input</button> <br /><br /> </div> <div> <p id="mytext"></p> </div> </body> </html>
5. QT调用JS
void MainWindow::on_actioncall_js_triggered() { QString funName = QString("setName(\"%1\");").arg(QString("mytext")); webView->page()->mainFrame()->evaluateJavaScript(funName); }
6. 加入Vue框架和element-ui
(1)element-ui依赖于Vue,所以不加入Vue就不能使用element-ui;
(2)要在<body>节点的外面加入Vue,否则由于Vue加载时间长,导致失效
(3)先加入Vue,再加入element-ui
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>scenario edit</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Language" content="Chinese"> <link rel="stylesheet" type="text/css" href="./element-ui/lib/theme-chalk/index.css"> <script language="javascript"> function setEvnItem() { alert("call Evnitem"); window.Evnitem.setMyItemText("call Evnitem"); } function setOpoItem() { //alert("call Opoitem"); window.Evnitem.secondSlot("call secondSlot"); } function setName(name) { alert(name); document.getElementById(name).innerHTML = name; } </script> </head> <body> <div id="app"> <h1>这是WebKit的一个应用</h1> <el-button v-on:click="SetEvn">setEvnItem input</el-button> <br /><br /> <el-button onclick="setOpoItem()"> setOpoItem input</el-button> <br /><br /> </div> <div> <p id="mytext"></p> </div> </body> <script type="text/javascript" src="./vue.js"></script> <script type="text/javascript" src="./element-ui/lib/index.js"></script> <script language="javascript"> //window.Evnitem.ObjSignal.connect(setEvnItem); new Vue({ el: '#app', data : {value: "setEvnItem"}, methods:{ SetEvn: function() { //alert("setEvnItem");
//这里直接调用QT注册的实例的函数
window.Evnitem.setMyItemText("call Evnitem"); //setEvnItem(); } } }) </script> </html>
代码中setEvnItem()和setOpoItem()两个函数可以删除,因为在Vue中可以直接调用注册的QT实体