QT浏览器(QWebKit)技术调研

之前被人错下了需求调研,竟然让我调研怎么用qt实现浏览器,想想也是醉了,但是没办法,不怕官就怕管啊,最后只好乖乖的调研了一番,还写了一个调研文档交付给了领导,哈哈,其实哪个公司会闲着没事自己做个浏览器呢?也没多大用处,可是万一有用呢,对吧!下面附上调研内容,欢迎拍砖!!

一、整体介绍

自定义浏览器的网页浏览功能实现主要使用QT自带的控件Qwebview,根据官方帮助文档其中Qwebview构成图如下图所示:

 

其中Qwebview用于查看和编辑网页,QWebiew打开的具体网页就是一个QWebPaged对象,一个QWebpage可以存在多个QWebFrame框架,目前自定义浏览器只使用了主框架即Qwebpage::mainFrame()。

QwebView可以再Qt界面设计器中手动拖入,也可以通过程序创建,自定义浏览器定义了一个继承QWebview类新类(CUserWebView),以便于实现其他高级功能。将CUserWebView添加到主界面中后,就可以实现浏览器的常用功能,自定义浏览器主要实现了网址输入、网页浏览、刷新、回退、前进、查看历史记录和查找等常用功能。各个功能实现方式如下:

  • 网址输入功能

创建网址输入编辑框(QLineEdit),并将网址输入编辑框添加到主界面的工具栏中,并将在编辑框中点击Enter键的信号与自定义槽函数OnChangeLocation()关联,自定义槽函数中调用QWebview类的load(strUrl)函数,完成网页的跳转显示。

  • 后退功能

在主界面工具栏中添加QWebPage::Back的Action函数,使用QwebPage的后退函数作为主界面的后退功能。

  • 前进功能:

在主界面工具栏中添加QWebPage:: Forward的Action函数,使用QwebPage的数前进函数作为主界面的前进功能。

  • 刷新功能

在主界面工具栏中添加QWebPage:: Reload的Action函数,使用QwebPage的刷新函数作为主界面的刷新功能。

  • 停止刷新功能

在主界面工具栏中添加QWebPage:: Stop的Action函数,使用QwebPage的停止函数作为主界面的停止功能。

  • 历史记录

历史记录功能的实现主要用到了QWebHsitory类,该类主要是用来存放QWebPage的访问历史记录,并且提供对于导航到相关页面的支持,自定义浏览器的历史记录功能实现流程如下:

说明:

  1. 在主界面工具栏中添加“历史记录”响应,点击时自动调用对应槽函数。
  2. 在槽函数中,通过QWebHistory的items函数获得所有历史记录对象(QList<QWebHistoryItem>)。
  3. 根据获取的所有历史记录,获取对应item的标题,并显示在QListWidget控件中。
  4. 关联QlistWidget的Click信号,点击列表时自动调用对应槽函数。
  5. 通过QWebHistory中的ItemAt(int i)获得点击Item, 并通过QWebhistoryItem中的url()函数获得对应的网址。
  6. 根据获得网址,调用Qwebpage中load函数,加载历史记录网页。
  • 查找功能

查找功能主要借助QWebPage中的findText函数实现查找功能,其声明如下:

bool findText(const QString &subString, FindFlags options = 0);

其中subString是传入的查找字符串,options是查找的处理标识,包括HighlightAllOccurrences(全部高亮)、FindCaseSensitively(区分大小写)等。

二、代理设置模块

代理设置模块主要是为了满足处于局域网的用户的上网需求,首先在系统自定义功能区添加设置按钮,用户点击设置按钮,自动弹出代理设置界面,如下图所示:

 

其中当“为LAN使用代理服务器”处于勾选状态时,地址和端口编辑框处于可用状态,否则为灰色不可用状态。代理设置的实现流程如下图所示:

说明:

  1. 当程序启动时,通过QNetworkProxy::applicationProxy()将当前应用程序的代理信息记录下来(程序中通过m_OldProxy记录),初始代理信息操作在系统整个生命周期中只执行一次,用于作为不使用代理的初始信息。
  2. 点击代理按钮,系统将当前代理设置信息数据传入到代理设置界面中,代理信息结构体定义如下:
struct ProxySetData
{

    // IP地址
    QString strHostName;
    // 端口
    int iPortNum;
    // 是否使用代理
    bool bUserProxyFlag; 

    ProxySetData()
    {
        bUserProxyFlag = false;
    }
};

代理设置界面根据bUserProxyFlag的值,来决定是否显示IP地址和端口号等信息。

  1. 根据需要自定义设置代理信息。
  2. 设置完成后,代理设置界面将代理信息结构体传到自定义功能区对象中,系统通过判断bUserProxyFlag的值判断是否使用代理。
  3. 不使用代理,则将代理设为初始代理(m_oldProxy),调用语句如下:
QNetworkProxy::setApplicationProxy(m_OldProxy);

     4.使用代理,则通过QNetworkProxy类的函数完成设置最新代理,调用语句如下:

QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName(m_stproxyData.strHostName);
proxy.setPort(m_stproxyData.iPortNum);
QNetworkProxy::setApplicationProxy(proxy);

   首先创建一个代理策略,然后设置代理类型(自定义浏览器默认使用http代理类型),然后设置代理地址、端口号,最后设置应用程序的代理信息后,即可完成代理设置。

三、JS与QT交互模块

在对JS与Qt交互模块进行了调查之后,下面结合合自定义浏览器中的功能,将通过JS调用QT函数、QT中调用JS函数、QT在JS网页中创建自定义控件和QT读取网页元素四个方面进行描述。

3.1 JS调用QT函数

通过自定义浏览器打开本地view.html文件,界面显示如图所示:

点击调用qt对象,弹出qt界面如下:

说明通过JS按钮调用QT对象成功。

上述过程的实现方式主要由以下几步:

【1】定义通信交互类,该类只要是QObj类的子类即可,该类的主要作用是用于提供JS函数调用的槽函数,因为JS中只能调用暴露对象的公有槽函数,因此该类中的槽函数都是公有的。此处定义了一个槽函数如下

【2】将槽函数的对象暴露给JS

在Cuserview类中添加通信交互类对象作为成员变量,然后将通信对象暴露给JS,该过程是通过QwebFrame类接口实现的:

page()->mainFrame()->addToJavaScriptWindowObject("JsWindowObj", m_JsWindowObjPtr);

其中”JsWIndowObj”是m_JsWindowObjPtr对象在Js文本中的名称,至于将通信对象暴露给JS的时机在官方文档中有推荐,即在javaScriptWindowObjectCleared()信号传来时进行暴露。即保留交互对象给JS的过程如下:

       1)在CuserView的构造函数中,关联信号与槽函数

connect(page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared ()),this, SLOT(OnAddJavaScriptObject()));

      2)在槽函数中将通信对象暴露给JS

void CUserWebView::OnAddJavaScriptObject()
{
     page()->mainFrame()->addToJavaScriptWindowObject("JsWindowObj",
     m_JsWindowObjPtr);

}

【3】在JS中调用暴露对象的槽函数,其中html文件内容如下:

此时点击“调用qt对象”按钮,调用JS中openSpiaclFile(file)函数,该函数调用暴露给Js的对象,JSWindowObj中的OnOpenUrl公有槽函数,该槽函数响应并弹出对应提示窗口。

3.2 QT调用JS函数

通过自定义浏览器打开本地view.html文件,界面如6.1节所示,点击测试按钮,系统弹出对话框如下所示:

说明通过JS按钮调用QT对象成功。

上述过程的实现方式与在6.1节基本类似,不同之处是需要在JS文件中绑定QT的信号,基本实现由以下几步组成:

【1】定义通信交互类,与6.1节完全相同,并在头文件中添加信号函数void ObjSignal(int value)。

【2】将槽函数的对象暴露给JS,此处与6.1节完全相同不在赘述。

【3】在Js中将信号与JS函数绑定,如下所示:

 

首先向暴露对象的信号与JS函数关联,其次定义该函数的相关操作。

【4】添加Qt中测试按钮的点击信号槽函数,在槽函数中发送暴露对象的信号。

四、QT在网页中创建自定义控件

通过QT可以再浏览器中添加自定义控件,主要通过重载QwebPage中的创建控件函数(createPlugin)实现,实现步骤如下,首先创建一个继承与QwebPage的类,在该类中重载createPlugin函数如下所示:

通过该函数实现了了一套创建对应插件的规则,目前在自定义浏览器中的规则十分简单主要用于测试使用,即如果calssid是pushbutton则创建pushbutton,并在按钮上显示ddd字样,如果是lineedit则创建lineedit控件。

然后在CuserView中使用该页面,即在构造函数中添加如下语句

 

最后创建对应的网页文件,创建文件内容如下

此时通过自定义浏览器打开该文件就会发现按钮创建成功,如下图所示:

通过上述方法创建的QtWebkit中插件可以有两种,一种type必须是application/x-qt-plugin或者application/x-qt-styled-widget的,如果需要去掉此限制,则需要重新实现QWebPluginFactory这个纯虚基类,此处没有继续深入调研。

五、QT读取网页元素

QWebview加载网页完成后可以读取网页中的各个元素节点信息,网页加载完成后通过如下语句获得顶级的网页:

QWebElement document = m_QWebviewPtr->page()->mainFrame()->documentElement();

然后根据获得document信息就可以进一步获取子级节点,以及节点内容等元素,下面简单列举QWebElement的相关函数:

QWebElement firstChild()     //获得第一个子节点
QWebElement  nextSibling() // 获得相邻节点
bool hasAttribute(const QString & name)  // 是否有该属性
……

总之,在QWebElement类中包含大量的解析网页的接口,可以获得当前加载网页的内部元素信息。

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值