基于QtWebkit的嵌入式bs架构设计

基于 QtWebkit 的嵌入式 bs 架构设计

                                                                      Write by tadaya

概述:本文旨在介绍如何使用 QtWebkit 来实现嵌入式客户端( browser ),而不关注 webkit 引擎的原理和任何效率问题。重点关注如何使用遥控器去操作网页中的元素(例如焦点移动,打开新的链接),这种应用在目前的 iptv 上应用非常广泛,通过实现自己的 browser ,可以加载不同的风格的界面(即网页),结合使用 qt 其他控件和 QtWebkit (框架)实现功能与界面完美结合的产品。

关键字:焦点, QtWebkit ,元素

一.嵌入式 BS 架构的优势。

嵌入式 bs 架构的设计与 pc 上的 bs 架构的区别:

1.pc 上无须自行设计浏览器,嵌入式需要对浏览器进行特殊处理。(如按键等)

2. 嵌入式需要加上对遥控器的支持。(如 tv 遥控器)

3.pc 上支持的网页元素比嵌入式要多。

4. 嵌入式需要做多套网页以适应不同屏幕的分辨率。

5. 嵌入式需要考虑 page cache flash 权衡的问题。

 

 

bs 架构比 cs 架构的优势:

1. 设计简单。大部分界面和部分功能都在后台服务器实现。

2. 界面炫丽。使用网页可以达到很炫的效果,显示格式也非常好控制。

3. 修改方便。基本上只需修改网页就可以了。

4. 可扩展性强。一个设计好的 browser 可以使用不同风格的网页,如:加载 youku 看电影,加载土豆看电影(不过这比较困难,焦点通过遥控器的移动在网页中链接,输入框, button 之间是一个非常困难的过程,嵌入式 flash player 很少)。

 

二. QtWebkit 的优势以及使用

QtWebkit 只是一个浏览器框架,其核心引擎时 webkit QtWebkit 简单的归纳为 webkit 的显示界面,即表现层和逻辑层的关系。 QtWebkit 的优势在于:

1.       可移植性强。 Linux windows embedded linux

2.       javascript 支持比较好。

3.       css 支持比较全面。

4.       封装比较好,简单易用。

 

需要用到 QtWebkit 时,需要在编译 QT 源码的时候,在 ./configure 加上 –webkit ,在编译自己的应用程序时,需要在 .pro 文件加上 QT+=webkit ,或者直接改 Makefile 加上 -lQWebkit ,简单的 browser 程序如下:

       int main(int argc, char* argv[])

{

    QApplication app(argc,argv);

 

     QWebview *view = new QWebview ();

     view->setGeometry(0,0,1024,1000);

         view->load(QUrl("www.baidu.com"));

      view->show();

         return app.exec();

}

 

3. 通过键盘(遥控器)控制网页元素

通过使用 QWebview QWebFrame QWebPage 类就基本上可以实现浏览器的所有功能,而我们重点关注是 QWebElement 这个类,该类封装了网页中 element ,即每个 <a></a> 就是一个 QWebElement 对象,不仅仅局限于 <a/>,<b/>,<head/> 等等都是一个 QWebElement ,而我们要通过遥控控制焦点的移动就需要调用 element.focus()( 注: qt 4.6 以后才有这个方法 )

 

举例说明:

需求 : 通过上下左右键来移动 baidu 中链接(即 <a> 元素),并改变相应链接的颜色。

实现分析:利用 QWebview 加载 baidu ,然后将 <a> 标签全部提取出来,放在 QWebElement list 中,(注:需要加载网页成功后才开始提取,否则会出现提取不到。即当 emit   signal loadFinished(bool) 后才开始提取)。重写 QWebview keyPressEvent 函数, QWebview 默认的上下左右键是当网页显示不下时滚动的处理,这点可通过源码以及默认的处理看出来,但可以通过 tab 键实现焦点移动,当收到上下左右键时可通过把按键事件改为 Qt :: Key_Tab 键事件来实现焦点移动(示例程序不是通过这种方法)。

改变相应链接的颜色有很多方法,暂列举 2 种:

1.       当焦点挪动时恢复原聚焦的元素的 style ,给现聚焦的元素加上新的 style

2.       自写一个通明控件,当焦点聚焦时将改空间放在元素对应的位置。

 

代码:

 

#include "browser.h"

#include <stdio.h>

 

browser::browser(QWidget * parent/* = 0 */):QWebView(parent)

{

    focusIndex = 0;

    frame=this->page()->currentFrame();

    frame->setScrollBarPolicy(Qt::Horizontal ,Qt::ScrollBarAlwaysOff);

    frame->setScrollBarPolicy(Qt::Vertical ,Qt::ScrollBarAlwaysOff);

    connect(this,SIGNAL(loadFinished(bool)),this,SLOT(loadPageFinish(bool)));

 

/* set webview no transparent */

       QPalette palette(QColor(255,0,0));

       this->setPalette(palette);

       this->setAttribute(Qt::WA_OpaquePaintEvent, false);

}

 

browser::~browser()

{

}

 

QString ed = "";

void browser::loadPageFinish(bool finish)

{

    if (finish)

    {

        focusIndex = 0;

        QWebFrame  *frame=this->page()->currentFrame();

        QWebElement  document=frame->documentElement();

        //printf("%s%s/n",ed.toLocal8Bit().data(),document.tagName().toLocal8Bit().data());

        //examineChildElements(document);

        elementList.clear();

        elementList = document.findAll("a").toList();

 

        if (elementList.size() > focusIndex)

        {

            QWebElement element;

            element = elementList.at(focusIndex);

 

            if (element.hasAttribute("style"))

            {

                preFocusStyle = element.attribute("style","");

            }

 

            element.setFocus();

            element.setAttribute("style", "background-color: #ff0000");

        }

    }

      

 

       /* set page transparent,so we can see view's background*/

       QPalette palette = this->palette();

       palette.setBrush(QPalette::Base, Qt::transparent);

       this->page()->setPalette(palette);

 

}

 

 

void browser::examineChildElements(const QWebElement &parentElement)

{

    ed += "  ";

    QWebElement element = parentElement.firstChild();

     while (!element.isNull())

    {

        printf("%s%s/n",ed.toLocal8Bit().data(),element.tagName().toLocal8Bit().data());

        if (element.hasFocus())

        {

            qDebug()<<element.tagName()<<"==============>";

        }

        if (element.toPlainText() == QString("hao123"))

        {

            element.setAttribute("style", "background-color: #ff0000");

            element.setFocus();

        };

        examineChildElements(element);

        if (ed.length()> 2)

        {

            ed.remove(0,2);

        }

 

 

        element = element.nextSibling();

    }

}

 

void browser::keyPressEvent(QKeyEvent * ev)

{

    switch (ev->key())

    {

        case Qt::Key_Right:

        case Qt::Key_Left:

        {

            if (elementList.size() > focusIndex)

            {

                QWebElement element = elementList.at(focusIndex);

                if (!element.isNull())

                {

 

                    if (element.hasAttribute("style"))

                    {

                         element.setAttribute("style", preFocusStyle);

                    }

 

                    focusIndex += 1;

                    if (elementList.size() == focusIndex)

                        focusIndex = 0;

                    element = elementList.at(focusIndex);

 

                    if (element.hasAttribute("style"))

                    {

                        preFocusStyle = element.attribute("style","");

                    }

 

                    element.setFocus();

                    element.setAttribute("style", "background-color: #ff0000");

//                     QLabel* label = new QLabel(this);

//                     label->setGeometry(element.geometry());

//                     label->setText("i am focus");

//                     label->show();

//                     label->raise();

                }

            }

        }

        break;

        default:

QWebView::keyPressEvent(ev);

}

}

 

 

程序效果图(一)

 

 

 

 

                                                               程序效果图(二)

运行效果图说明:

1.       初始焦点在“登录”(第一个链接)

2.       移动后新焦点被我们设置 style 为红色。

3.       QWebView 默认的 enter 键会打开链接地址。

 

总结:上述程序只能左移到上一个链接或者右移到下一个链接,这种控制焦点的方式在简单的几个链接的网页比较合适,在需要精确的控制焦点移动时,最好通过网页本身去做(如调用 js 脚本等), QWebview 调用 js 脚本以及与 js 通信的示例资料网上很多,这里不做陈述。

该示例程序重点旨在介绍焦点在网页如何移动,这对做无鼠标嵌入式开发人员来说比较重要, enjoy it

你可能感兴趣的:(架构设计,嵌入式,webkit,qt,browser,behavior)