1. 程式人生 > >QT Web與本地應用的混合開發

QT Web與本地應用的混合開發

本文介紹了在Qt中如何開發Web本地混合應用,以及如何讓js與c++雙向呼叫。附帶幾個簡單例項。

接觸Qt也就兩個星期多吧,所以文章中難免有幼稚和錯誤的地方,請各位不吝賜教。

個人認為標記語言描述的介面是介面開發的一個發展趨勢。WPF、Java FX,當然也少不了Html。

基於Html的介面在開發效率,可移植性上都十分有優勢,所以也被很多程式採用,只是我們平時沒注意到而已。比如:

image

image

Chrome的網頁除錯工具本身就是一個網頁,不信你可以右鍵點選,選檢視原始碼。

其它的還有像ServU和VMware Server等,懶的截圖了。

下面進入正題,用QT做Web與本地應用的混合開發

因為QT中集成了Webkit,拿來做這種還是一件相當happy的事(什麼?為什麼要用Webkit?你想自己寫一個瀏覽器引擎不成?)

image

新建一個Qt Gui專案,記得選上QtWebKit和QNetwork(這個後面要用到)。

寫如下一段程式碼,一個瀏覽器就做成了:

01 #include <QtGui/QApplication>
02 #include <QWebView>
03 #include <QMainWindow>
04
05 int main(int argc, char *argv[])
06 {
07 QApplication a(argc, argv);
08 QMainWindow window;
09 QWebView view(&window);
10 view.setGeometry(0, 0, 600, 400);
11
12 window.show();
13 return a.exec();
14 }

如圖:

image

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

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

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

setUrl的話,更用技術含量一點,可能需要自己做一個簡單的Http伺服器,(不考慮效率優化的話也沒那麼難),然後監聽本地埠,掉用QWebView的setUrl(QUrl(http://127.0.0.1:XXXX))就可以了。

我用了一種更省事的方法:直接把要顯示的html放到apache上去了。這樣連PHP也可以用了,哈哈哈哈~(咦,磚頭?)

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

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

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

下面說一種更好的方法,實現js與C++的雙向呼叫

js呼叫c++方法

首先要將一個C++的物件“送”到js中,js拿到這個物件以後就可以像其它物件一樣,自由的呼叫它的方法了。

這一步有兩種實現方式:

1. 在網頁中插入控制元件

JS端: 在網頁中插入下面一段程式碼:

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

之後就可以通過document.getElementById(‘qt’);獲取這個物件,並呼叫方法了。

C++端:

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

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

然後過載QWebPage中的如下方法(protected的)

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

方法的返回值就是要傳遞紿js的物件。

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

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

MyWidget.h

01 #ifndef MYWIDGET_H
02 #define MYWIDGET_H
03
04 #include<QWidget>
05 #include<QWebPage>
06 #include<QWebFrame>
07
08 class MyWidget :public QWidget {
09 Q_OBJECT
10 private:
11 QWebPage *page;
12 public:
13 MyWidget(QWebPage *page) : page(page) { }
14 public slots:
15 void func(QString arg) {
16 this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';");
17 }
18 };
19
20 #endif // MYWIDGET_H

MyPage.h

01 #ifndef MYPAGE_H
02 #define MYPAGE_H
03
04 #include<QWebPage>
05 #include<QWebFrame>
06 #include"MyWidget.h"
07
08 class MyPage : public QWebPage {
09 Q_OBJECT
10 public:
11 MyPage(QObject *parent = 0) : QWebPage(parent) {
12 settings()->setAttribute(QWebSettings::PluginsEnabled, true);
13 }
14 protected:
15 QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues){
16 return new MyWidget(this);
17 }
18 };
19
20 #endif // MYPAGE_H

main.cpp

01 #include <QtGui/QApplication>
02 #include <QMainWindow>
03 #include <QWebView>
04 #include <QWebPage>
05 #include <QWebFrame>
06 #include "MyPage.h"
07
08 int main(int argc, char *argv[])
09 {
10 QApplication a(argc, argv);
11 QMainWindow window;
12 QWebView view(&window);
13 MyPage page;
14 view.setPage(&page);
15 view.setGeometry(0, 0, 600, 400);
16 // Object
17 QString content("<object type='application/x-qt-plugin' height='1' width='1' id='qt'></object>");
18 // JS Function f() : Invoke the 'func' function
19 content += "<script>document.getElementById('qt').func('http://pnuts.cc');</script>";
20 view.setContent(content.toAscii());
21 window.show();
22 return a.exec();
23 }

執行結果如下:

image

2. 用QWebFrame的addToJavaScriptWindowObject方法

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

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

注意:addToJavaScriptWindowObject的第一個引數是物件在js中的變數名,第二個引數的QObject不要求是QWidget。

MyObject.h

01 #ifndef MYOBJECT_H
02 #define MYOBJECT_H
03
04 #include<QObject>
05 #include<QWebPage>
06 #include<QWebFrame>
07
08 // !! ATTENTION !! : The object do NOT need to inherit from QWidget anymore.
09 class MyObject :public QObject {
10 Q_OBJECT
11 private:
12 QWebPage *page;
13 public:
14 MyObject(QWebPage *page) : page(page) { }
15 public slots:
16 void func(QString arg) {
17 this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';");
18 }
19 };
20
21 #endif // MYOBJECT_H

main.cpp

01 #include <QtGui/QApplication>
02 #include <QMainWindow>
03 #include <QWebView>
04 #include <QWebPage>
05 #include <QWebFrame>
06 #include "MyObject.h"
07
08 int main(int argc, char *argv[])
09 {
10 QApplication a(argc, argv);
11 QMainWindow window;
12 QWebView view(&window);
13 QWebPage page;
14 view.setPage(&page);
15 view.setGeometry(0, 0, 600, 400);
16 MyObject obj(&page);
17 page.mainFrame()->addToJavaScriptWindowObject("qt", &obj);
18 QString content("<script>function f() { qt.func('http://pnuts.cc'); }</script>");
19 content += "<a href="#" clicktoshowdialog="dialogJsLink">Click Me</a>";
20 view.setContent(content.toAscii());
21 window.show();
22
23 return a.exec();
24 }

至於為什麼要用個連結點一下再顯示而不是直接執行,自己去想,想不清再來問。

image

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

01 #ifndef MYOBJECT_H
02 #define MYOBJECT_H
03
04 #include<QObject>
05 #include<QWebPage>
06 #include<QWebFrame>
07
08 class MyObject :public QObject {
09 Q_OBJECT
10 private:
11 QWebPage *page;
12 public:
13 MyObject(QWebPage *page) : page(page) { }
14 signals:
15 void Miku();
16 public slots:
17 void viewLoad() {
18 this->page->mainFrame()->evaluateJavaScript("qt.Miku.connect(f);");
19 this->Miku();
20 }
21 };
22
23 #endif // MYOBJECT_H

main.cpp

01 #include <QtGui/QApplication>
02 #include <QMainWindow>
03 #include <QWebView>
04 #include <QWebPage>
05 #include <QWebFrame>
06 #include "MyObject.h"
07
08 int main(int argc, char *argv[])
09 {
10 QApplication a(argc, argv);
11 QMainWindow window;
12 QWebView view(&window);
13 QWebPage page;
14 view.setPage(&page);
15 view.setGeometry(0, 0, 600, 400);
16 MyObject obj(&page);
17 QObject::connect(&view, SIGNAL(loadFinished(bool)), &obj, SLOT(viewLoad()));
18 page.mainFrame()->addToJavaScriptWindowObject("qt", &obj);
19 QString content("<script>function f() { document.body.innerHTML += 'http://pnuts.cc'; }</script>");
20 view.setContent(content.toAscii());
21 window.show();
22 return a.exec();
23 }

接觸Qt也就兩個星期多吧,所以文章中難免有幼稚和錯誤的地方,請各位不吝賜教。

最後放幾個自己linux作業(本來也是因為linux作業才接觸的Qt)的截圖吧:

只追求意識流,不追求功能和使用者體驗。後面的陰影是滑動的,圖片就看不出來了。

image

(登陸視窗)

image

(聊天視窗1)

image

(聊天視窗2)

image image

(隱藏版的HX主題和鮮花主題)

相關推薦

QT Web本地應用混合開發

本文介紹了在Qt中如何開發Web本地混合應用,以及如何讓js與c++雙向呼叫。附帶幾個簡單例項。 接觸Qt也就兩個星期多吧,所以文章中難免有幼稚和錯誤的地方,請各位不吝賜教。 個人認為標記語言描述的介面是介面開發的一個發展趨勢。WPF、Java FX,當然也少不了Ht

《React Native 精解實戰》書籍連載「Android 平臺 React Native 混合開發

此文是我的出版書籍《React Native 精解與實戰》連載分享,此書由機械工業出版社出版,書中詳解了 React Native 框架底層原理、React Native 元件佈局、元件與 API 的介紹與程式碼實戰,以及 React Native 與 iOS、Android 平臺的混合開發底層原理講解與程式

AppInterface,一套AndroidH5的混合開發框架

最近的工作主要是圍繞APP與內嵌H5開發而展開的,所以寫了個小框架,以期能提升客戶端童鞋與前端童鞋的開發效率。具有Android與H5兩部分內容,互相搭配使用,介面簡潔,執行效率高,使用簡便,能極大的提升開發效率。 下方是github地址: https:/

Hybrid App: 瞭解JavaScript如何Native實現混合開發

一、簡介 Hybrid Development混合開發是目前移動端開發異常火熱的新興技術,它能夠實現跨平臺開發,極大地節約了人力和資源成本。跨平臺開發催生了很多新的開源框架,就目前而言,在混合開發中比較流行的有FaceBook開源React Native,有Goggle開源的Flutter。React Nat

移動web:原生開發打包,嵌入h5頁面 webApp:全部都是H5開發應用 混合APP:使用第三方開發平臺從apicloud,appcan,hbuilder等開發,cordova技術打包 原生APP:就是eclipse開發或者studio等工具開發

應用 手機 .com net ack 自動連接 pan 經驗 使用 論壇43213 移動端webApp兼容問題解決 談談App混合開發 Hybrid APP混合開發的一些經驗和總結 PhoneGap是一個采用HTML,CSS和JavaScript的技術,創建

Android混合開發-(AndroidWeb的互動)

在Android開發中,越來越多的商業專案使用了Android原生控制元件與WebView進行混合開發,當然不僅僅就是顯示一個WebView那麼簡單,有時候還需要本地Java程式碼與HTML中的JavaScript進行互動,Android也對互動做了很好的封裝,所以很容易實現例如:點選網頁中的按鈕A

PHP Delphi 混合開發 Web 程式

    需求:    有一個桌面軟體,需要通過機器碼產生序列號,這個過程需要在一個網站後臺完成。而產生序列號的程式碼是用 Delphi 編寫的,此程式碼移植到 PHP 語言下有一定的困難,或者無法完成。於是產生了 PHP 呼叫 Delphi 程式碼的問題。     解決方案及

python的高效能web應用開發測試實驗

➜ / ab -n 200 -c 40 http://localhost:8009/demo/syncsleep-handler/ This is ApacheBench, Version 2.3 <$Revision: 1528965 $> Copyright 1996 Adam T

利用CEFSharp在WPF中顯示網頁(可實現PC端的混合開發,Web硬體互動)

最近遇見Web應用需要呼叫身份證讀卡器等硬體介面,按照一般解決辦法封裝一個OCX控制元件就完事了。但是問題就出現了,目前只有IE支援ActiveX控制元件,IE載入控制元件還需要點“允許”等等。由於本人比較抵觸IE的,所以看這樣的實現方式怎麼都是不爽就對了(我想很多人都是這樣

Web應用程序開發,基於Ajax技術的JavaScript樹形控件

實現 web應用 建立 tar 框架 目前 動態生成 方案 技術問題 感謝http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web應用程序開發領域,基於Ajax技術的JavaScript樹形控件已經被廣泛使用,

iOS開發中的position+anchorPointframe應用解釋

移動 pos 限制 一起 frame -1 必須 posit 解釋 我剛開始時非常困惑這兩個地方, 所以現在好好解釋一下他們的聯系. 1/ position與anchorPoint是一對屬性, 經常一起設置來確定控件的位置 frame單獨設置 2/ position

web應用後臺開發的故事

效果 渲染 後臺 web 幫助 指導 實體 完成 信息 開發一個web應用程序和開發一個網站是不同的。雖然在總體上由很多相似之處,但開發他們所需要的時間有巨大的差別。 應用軟件,通常也被稱為應用。指的是專門為幫助用戶去執行一個或者多個相關特定任務而設計的計算機軟件。

一個實現瀏覽器網頁本地程序之間進行雙向調用的輕量級、強兼容、可擴展的插件開發平臺—本網通

特殊 git 運行環境 mac office文檔 linu 網頁 中繼 安全 通過本網通插件平臺可實現在網頁中的JavaScript腳本無障礙訪問本地電腦的硬件、調用本地系統的API及相關組件,同時可徹底解決ActiveX組件在Chrome、FireFox、Opera、Ed

android 開發之 ListView Adapter 應用實踐

在開發android中,ListView 的應用顯得非常頻繁,只要需要顯示列表展示的應用,可以說是必不可少,下面是記錄開發中應用到ListView與Adapter 使用的例項: ListView 所在頁面中的佈局(listview_item.xml): <?xml version="1.0"

深入剖析 Web 伺服器 PHP 應用之間的通訊機制 - 掌握 CGI 和 FastCGI 協議的執行原理

本文首發於 深入剖析 Web 伺服器與 PHP 應用之間的通訊機制 - 掌握 CGI 和 FastCGI 協議的執行原理,轉載請註明出處! 身為一名使用 PHP 語言開發後端服務的程式猿,我們每天都和 PHP 以及 Web 伺服器產生無數次的親密接觸。得益於它們,我們才能

混合開發 Hybird Ionic Angular Cordova web 跨平臺

混合開發 Hybird Ionic Angular Cordova web 跨平臺 目錄 目錄 Ionic Ionic 簡介 Ionic 和 Cordova/PhoneGap 的關係 零基礎案例 環境配置 下載 淘寶映象 cnpm 安裝 ionic

web伺服器、應用伺服器、web容器、反向代理伺服器區別聯絡

Web伺服器工作原理 HTTP協議基於TCP協議上,是一個應用層協議,用於使用者代理和Web伺服器進行通訊。Web伺服器通常採用一問一答的方式進行工作: 在使用者代理上使用者發起資源請求,請求內容包括但不限於:指定資源的唯一標識URI,指明動作型別(GET/POS

基於Web開放平臺的應用開發的一些研究

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Vue.js前端開發快速入門專業應用

blank 角度 前端 介紹 實際應用 運用 get 指令 http 本書主要介紹 Vue.js 的使用方法和在實際項目中的運用,它既可以在一個頁面中單獨使用,也可以將整站都構建成單頁面應用。為了便於理解,本書會從傳統的開發角度切入,先從數據渲染、事件綁定等方面介紹在 Vu

PythonC/C++混合程式設計的應用

我看到的一個很好的Python與C/C++混合程式設計的應用是NS3(Network Simulator3)一款網路模擬軟體,它的內部計算引擎需要用高效能,但在使用者建模部分需要靈活易用。NS3的選擇是使用C/C++來模擬核心部件和協議,用python來建模和擴充套件。 這篇文章介紹Python和C/C++