詳解基于Qt Webkit嵌入式BS架構設計
基于Qt Webkit嵌入式BS架構設計是本文要介紹的內容,主要介紹如何使用 Qt Webkit 來實現(xiàn)嵌入式客戶端( browser ),而不關注 webkit 引擎的原理和任何效率問題。
重點關注如何使用遙控器去操作網(wǎng)頁中的元素(例如焦點移動,打開新的鏈接),這種應用在目前的 iptv 上應用非常廣泛,通過實現(xiàn)自己的 browser ,可以加載不同的風格的界面(即網(wǎng)頁),結合使用 qt 其他控件和 QtWebkit (框架)實現(xiàn)功能與界面***結合的產品。
一、嵌入式 BS 架構的優(yōu)勢
嵌入式 bs 架構的設計與 pc 上的 bs 架構的區(qū)別:
1、pc 上無須自行設計瀏覽器,嵌入式需要對瀏覽器進行特殊處理。(如按鍵等)
2、嵌入式需要加上對遙控器的支持。(如 tv 遙控器)
3、pc 上支持的網(wǎng)頁元素比嵌入式要多。
4、嵌入式需要做多套網(wǎng)頁以適應不同屏幕的分辨率。
5、嵌入式需要考慮 page cache 和 flash 權衡的問題。
bs 架構比 cs 架構的優(yōu)勢:
1、設計簡單。大部分界面和部分功能都在后臺服務器實現(xiàn)。
2、界面炫麗。使用網(wǎng)頁可以達到很炫的效果,顯示格式也非常好控制。
3、修改方便。基本上只需修改網(wǎng)頁就可以了。
4、可擴展性強。一個設計好的 browser 可以使用不同風格的網(wǎng)頁,如:加載 youku 看電影,加載土豆看電影(不過這比較困難,焦點通過遙控器的移動在網(wǎng)頁中鏈接,輸入框, button 之間是一個非常困難的過程,嵌入式 flash player 很少)。
二、QtWebkit 的優(yōu)勢以及使用
QtWebkit 只是一個瀏覽器框架,其核心引擎時 webkit , QtWebkit 簡單的歸納為 webkit 的顯示界面,即表現(xiàn)層和邏輯層的關系。 QtWebkit 的優(yōu)勢在于:
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、通過鍵盤(遙控器)控制網(wǎng)頁元素
通過使用 QWebview , QWebFrame , QWebPage 類就基本上可以實現(xiàn)瀏覽器的所有功能,而我們重點關注是 QWebElement 這個類,該類封裝了網(wǎng)頁中 element ,即每個 <a></a> 就是一個 QWebElement 對象,不僅僅局限于 <a/>,<b/>,<head/> 等等都是一個 QWebElement ,而我們要通過遙控控制焦點的移動就需要調用 element.focus()( 注: qt 4.6 以后才有這個方法 ) 。
舉例說明:
需求 : 通過上下左右鍵來移動 baidu 中鏈接(即 <a> 元素),并改變相應鏈接的顏色。
實現(xiàn)分析:利用 QWebview 加載 baidu ,然后將 <a> 標簽全部提取出來,放在 QWebElement list 中,(注:需要加載網(wǎng)頁成功后才開始提取,否則會出現(xiàn)提取不到。即當 emit signal loadFinished(bool) 后才開始提?。?。
重寫 QWebview 的 keyPressEvent 函數(shù), QWebview 默認的上下左右鍵是當網(wǎng)頁顯示不下時滾動的處理,這點可通過源碼以及默認的處理看出來,但可以通過 tab 鍵實現(xiàn)焦點移動,當收到上下左右鍵時可通過把按鍵事件改為 Qt :: Key_Tab 鍵事件來實現(xiàn)焦點移動(示例程序不是通過這種方法)。
改變相應鏈接的顏色有很多方法,暫列舉 2 種:
1、當焦點挪動時恢復原聚焦的元素的 style ,給現(xiàn)聚焦的元素加上新的 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);
- }
- elementelement = 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);
- }
- }
總結:上述程序只能左移到上一個鏈接或者右移到下一個鏈接,這種控制焦點的方式在簡單的幾個鏈接的網(wǎng)頁比較合適,在需要精確的控制焦點移動時,***通過網(wǎng)頁本身去做(如調用 js 腳本等), QWebview 調用 js 腳本以及與 js 通信的示例資料網(wǎng)上很多,這里不做陳述。
小結:詳解基于Qt Webkit嵌入式BS架構設計的內容介紹完了,希望通過本文的學習能對你有所幫助!