Qt學習 之 QWebView


WebKit 是一個開源的瀏覽器引擎,目前 Safari,Chrome 等瀏覽器均使用了 WebKit 作為核心。Qt 從 4.5 版本開始,集成了 WebKit 作為 Qt 的平台組件,用戶可以像使用其他組件一樣將 WebKit 引擎集成到自己的應用程序中,以提供 Web 的支持。

Qt 中對 WebKit 做了封裝,主要有以下幾個類:

QWebView 最常用的類,這是一個窗體控件,可以用來渲染網頁 。
QWebPage 被 QWebView 包含,表示一個 document。

QWebFrame 被 QWebPage 包含,表示一個 frame。

QWebSettings    Web 渲染的全局設置。

QWebHistory 用於瀏覽的歷史記錄。

圖 1. QWebView 的結構圖

QWebView 使用 QWebPage 來實現頁面,QWebPage 使用 QWebFrame 來實現頁面元素。

以下是參考文章

之前在做CS架構的時候,顯示圖表總是做得不好。只有C#有相應的組件,QT需要手畫或者加載一些插件。做了BS架構之后,知道了很多在前端方面表現極佳的圖表制作工具,如Echarts。在上一次的大作業之中,也使用了這一方法。那么又知道QT里可以加載QtWebKit,因此便可以進行Web與本地應用的混合開發。

這里寫圖片描述

新建一個Qt Gui項目,記得選上QtWebKit和QNetwork。

QWebView類

使用QWebView類只要幾行代碼就可以做出一個最簡單的瀏覽器。QWebView的主要功能是用於瀏覽網頁,每個QWebView都包含着一個QWebPage,而QWebPage是用於存儲和編輯網頁的類。

下面是一個最簡單的瀏覽器了:main.cpp

#include <QtGui/QApplication> #include <QWebView> #include <QMainWindow> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow window; QWebView view(&window); view.setGeometry(0, 0, 600, 400); view.setUrl(QUrl("https://github.com/Mr-Phoebe")); window.show(); return a.exec(); }

webpage.pro:

TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += qt QT += webkit # Input SOURCES += main.cpp 

QWebView有兩種方法可以用來設定要顯示的內容,一個是setUrl方法,一個是setContent方法。 這個很簡單,試一下就會,不多說了。

不過對這兩種方法會有兩種不同的開發方式:

setContent的話,需要手動將網頁代碼生成出來放到QWebView中,網頁中的元素(如:圖片,樣式,腳本)就只能采用“file:///”的方式了。

setUrl的話,更用技術含量一點,可能需要自己做一個簡單的Http服務器,然后監聽本地端口,掉用QWebView的setUrl(QUrl(http://127.0.0.1:XXXX))就可以了。

可以使用一種更省事的方法:直接把要顯示的html放到apache上去了。

顯示出來並不難,最主要的是如何同界面雙向交互,又不是asp,總不能沒點按鈕就刷一次頁面吧。

最容量想到的是傳統Web開發的中常用的Ajax,不過就有兩個缺點:

一個是要監聽本地端口,第二個更致命,Ajax不是雙向的,Server向Client發消息就不行了。

下面說一種更好的方法,實現js與C++的雙向調用。

js調用c++方法

首先要將一個C++的對象“送”到js中,js拿到這個對象以后就可以像其它對象一樣,自由的調用它的方法了。

這一步有兩種實現方式:

1. 在網頁中插入控件

JS端

在網頁中插入下面一段代碼:

<object type="application/x-qt-plugin" id="qt"></object>

之后就可以通過document.getElementById(‘qt’);獲取這個對象,並調用方法了。

C++端

首先要自定義一個類繼承自QWebPage,在構造函數中加入如下一句話開起plugin的支持。

settings()->setAttribute(QWebSettings::PluginsEnabled, true);

然后重載QWebPage中的如下方法(protected的)

virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);

方法的返回值就是要傳遞紿js的對象。

注意:返回值要是一個QWidget *類型的,所以可能還要自己自己寫一個Widget,寫好后,返回的QWidget中的所有public slots在js中都是可見的方法。

例子如下,有點長,不過很簡單:

MyWidget.h

#ifndef MYWIDGET_H #define MYWIDGET_H #include<QWidget> #include<QWebPage> #include<QWebFrame> class MyWidget :public QWidget { Q_OBJECT private: QWebPage *page; public: MyWidget(QWebPage *page) : page(page) { } public slots: void func(QString arg) { this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';"); } }; #endif // MYWIDGET_H

 

MyPage.h

#ifndef MYPAGE_H #define MYPAGE_H #include<QWebPage> #include<QWebFrame> #include"MyWidget.h" class MyPage : public QWebPage { Q_OBJECT public: MyPage(QObject *parent = 0) : QWebPage(parent) { settings()->setAttribute(QWebSettings::PluginsEnabled, true); } protected: QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues){ return new MyWidget(this); } }; #endif // MYPAGE_H

main.cpp

#include <QtGui/QApplication> #include <QMainWindow> #include <QWebView> #include <QWebPage> #include <QWebFrame> #include "MyPage.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow window; QWebView view(&window); MyPage page; view.setPage(&page); view.setGeometry(0, 0, 600, 400); // Object QString content("<object type='application/x-qt-plugin' height='1' width='1' id='qt'></object>"); // JS Function f() : Invoke the 'func' function content += "<script>document.getElementById('qt').func('https://github.com/Mr-Phoebe');</script>"; view.setContent(content.toAscii()); window.show(); return a.exec(); }

2. 用QWebFrame的addToJavaScriptWindowObject方法

相比上一個方法,個人推薦這種方法。因為上一個在Linux下遇到過很詭異的問題。

例子是最好的說明方式,於是再紿出一下例子:

注意:addToJavaScriptWindowObject的第一個參數是對象在js中的變量名,第二個參數的QObject不要求是QWidget。

MyObject.h

#ifndef MYOBJECT_H #define MYOBJECT_H #include<QObject> #include<QWebPage> #include<QWebFrame> // !! ATTENTION !! : The object do NOT need to inherit from QWidget anymore. class MyObject :public QObject { Q_OBJECT private: QWebPage *page; public: MyObject(QWebPage *page) : page(page) { } public slots: void func(QString arg) { this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';"); } }; #endif // MYOBJECT_H

main.cpp

#include <QtGui/QApplication> #include <QMainWindow> #include <QWebView> #include <QWebPage> #include <QWebFrame> #include "MyObject.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow window; QWebView view(&window); QWebPage page; view.setPage(&page); view.setGeometry(0, 0, 600, 400); MyObject obj(&page); page.mainFrame()->addToJavaScriptWindowObject("qt", &obj); QString content("<script>function f() { qt.func('https://github.com/Mr-Phoebe'); }</script>"); content += "<a href='javascript:f()'>Click Me</a>"; view.setContent(content.toAscii()); window.show(); return a.exec(); }

C++調用js代碼

依舊是兩種方法。

1. evaluateJavaScript

這個超簡單了,上面的例子中就用到了。不多說了。

2. connect

這個更符合Qt的風格一點。首先用上一部分介紹的兩種方法中的任意一種將一個C++對象“送”到js中去。然后調用這個對象的connect方法,將自己的signals和js方法進行bind。

再放個例子吧,不過例子中竟然用evaluateJavaScript來bind。

當QWebView加載好后,綁定MyObject的Miku Signal到js本地方法f,再觸發Miku Signal。

MyObject.h

#ifndef MYOBJECT_H #define MYOBJECT_H #include<QObject> #include<QWebPage> #include<QWebFrame> class MyObject :public QObject { Q_OBJECT private: QWebPage *page; public: MyObject(QWebPage *page) : page(page) { } signals: void Miku(); public slots: void viewLoad() { this->page->mainFrame()->evaluateJavaScript("qt.Miku.connect(f);"); this->Miku(); } }; #endif // MYOBJECT_H

main.cpp

#include <QtGui/QApplication> #include <QMainWindow> #include <QWebView> #include <QWebPage> #include <QWebFrame> #include "MyObject.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow window; QWebView view(&window); QWebPage page; view.setPage(&page); view.setGeometry(0, 0, 600, 400); MyObject obj(&page); QObject::connect(&view, SIGNAL(loadFinished(bool)), &obj, SLOT(viewLoad())); page.mainFrame()->addToJavaScriptWindowObject("qt", &obj); QString content("<script>function f() { document.body.innerHTML += 'http://pnuts.cc'; }</script>"); view.setContent(content.toAscii()); window.show(); return a.exec(); }

轉自:http://blog.csdn.net/u013007900/article/details/52159795


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM