[-]
- Qt和Javascript互動的兩種方式
- 執行個體分析
- 前端——HTML和Javascript
- 後台——Qt
- 小結
- 附錄
轉載請註明出處:http://blog.csdn.net/footman_/article/details/6694161
目錄
1 Qt和Javascript互動的兩種方式
2 執行個體分析
2.1 前端——HTML和Javascript
2.2 後台——Qt
3 小結
4 附錄
1 Qt和Javascript互動的兩種方式
為了充分發揮Javascript的跨平台特性,Qt和JavaScript互動將不採用“Qt對Javascript公開對象引用”的方式(即通過QWebFrame的addToJavaScriptWindowObject方法向Javascript提供對象引用)。這種方式雖然使得Qt和JavaScript能直接的互動,但是Javascript端對於Qt端的依賴將影響Javascript發揮跨平台性。該方式調用原理1-1中左圖所示:
圖1-1
不難看出,左邊的方式中Javascript對Qt對象的依賴不利於Javascript往其它平台移植。
而右邊的“自訂URL”方式則不一樣,Javascript不再選擇利用Qt對象去調用Qt方法,而是直接向Webkit瀏覽器發送自訂URL,Webkit捕獲到URL後通過QWebKit自身提供的Signal來關聯Qt中的Slots函數,並向Slots函數傳遞URL,Slots函數就可以根據URL中的資訊作出相應處理。在“自訂URL”方式中,底層平台不論是Qt,還是Android,上層的Javascript只需發送“自訂URL”即可。這樣Javascript的平台無關性就能得以充分發揮。1-2所示:
圖1-2
2執行個體分析
對“自訂URL”方式有了初步認識後,下面通過一個執行個體來敘述這種“自訂URL”的方式中可能涉及到的技術點。
2.1 前端——HTML和Javascript
例子中涉及2個html檔案a.html、b.html和一個Javascript檔案js.js。檔案b.html很簡單,就是一句歡迎語,檔案a.html運行2-1所示:
圖2-1
其對應的代碼如下:
<html>
<script language="JavaScript" type="text/javascript" src="js.js"></script>
<body>
<center>
<span>text a:</span>
<input type="text" name="aText" id="aText" />
<input type="submit" value="Go" onclick="javascript:sendURL()" />
<a href="b.html">b.html</a>
<font color=red><div id=warning></div></font>
</center>
</body>
</html>
該html檔案中引用到的js.js代碼如下:
function sendURL()
{
var value = document.getElementById("aText").value.replace(/\s/g,"");
if(value != "")
{
if(confirm("Go to " + value +"?"))
{
location.href = value;
}
}
else
{
document.getElementById("warning").innerHTML = "Please Input Target";
}
}
2.2 後台——Qt
從a.html和js.js端的代碼不難看出,當使用者在a.html頁面上文字框內輸入內容後,點擊“Go”按鈕就會觸發js.js中的sendURL方法,該方法會把使用者在文字框內輸入的內容當作URL發送,那麼背景Qt端如何得到這個URL呢?
2.2.1 loadStarted訊號
通過查閱Qt協助文檔找到這樣一個訊號——loadStarted(),該訊號在QWebView、QWebPage和QWebFrame均存在。當開始載入一個新的網頁時產生該訊號,所以接收Javascript產生的URL可以嘗試從該訊號入手。
2.2.2 requestedUrl函數
QWebFrame有個方法叫做requestedUrl()。當產生URL請求而載入Web頁面時,調用該方法能過擷取到請求的URL。看來接收Javascript產生的URL,這個方法不可或缺。
2.2.3 擷取URL
下面結合前面選擇的訊號和方法來擷取Javascript產生的URL。
1、為loadStarted訊號設定Slots函數
QWebPage * page = view->page();
connect(page, SIGNAL(loadStarted()), this, SLOT(doLoad()));
2、接收URL
void MyMainWindows::doLoad()
{
QUrl url = view->page()->mainFrame()->requestedUrl();
qDebug()<<"doLoad...."<<url;
/*解析URL*/
parseURL(url);
}
parseURL的具體實現參見附錄。
2.2.4 示範執行個體
接收成功後,就可以由Qt解析URL,由URL中的資訊來選擇應該執行什麼操作。
在本例子中,如果URL是字串“print”,那麼就調用“print”相關模組(簡單的輸出資訊,然後跳轉到b.html頁面)。圖2-2為執行個體運行後的主介面:
圖2-2
輸入print,點擊“Go”按鈕,介面切換,2-3所示:
圖2-3
同時觀察控制台輸出,2-4所示:
圖2-4
從輸出資訊中可以看出,接收到的URL為檔案絕對路徑,解析後比較URL,如果等於“print”,那麼就執行“Call Moudle Of Print”,並載入b.html。
注意,載入b.html頁面時同樣會因為產生loadStarted訊號而執行預先設定好的Slots函數。至此示範完畢!
3小結
在小結之前先來看a.html中埋下的一個小伏筆。
在a.html中有個超連結“b.html”,該連結的URL指向b.html頁面,正常情況下點擊該連結就會跳轉到b.html頁面,但為何在本執行個體程式中點擊b.html不會有任何跳轉呢?
這其中的原因在於QWebKit中的linkClicked訊號,當點擊Web頁面中的超連結時就會產生該訊號。本例中為該訊號設定Slots函數,函數中沒有對超連結的URL進行載入,所以點擊超連結後不會產生任何跳轉。類似於linkClicked這樣的訊號還有很多,可以根據不同的需求選擇使用。
對比兩種互動方式,“Qt對Javascript公開對象引用”的方式在Javascript調用Qt的過程中表現得較為直接,而“自訂URL”的互動方式很好地解決了跨平台問題。總之,方案沒有好壞之分,各有所長,根據實際需求選取即可。
4附錄
1、parseURL方法具體實現如下:
void MyMainWindows::parseURL(QUrl url)
{
QString urlStr = url.toString();
qDebug()<<"parseURL...."<<urlStr;
/*
* 因為每次調用load都會觸發loadStarted訊號而執行該方法,
* 所以必須保證load網頁時不會解析URL,否則load不到網頁。
*/
if(urlStr.right(5).operator != (QString(".html")))
{
int len = urlStr.length();
qDebug()<<"urlStr.length():"<<len;
QString ret = urlStr.right(len-24);
qDebug()<<"Start Parse Url:"<<ret;
if(ret.operator==(QString("print")));
{
qDebug()<<"Call Moudle Of Print";
/*如果找不到該url,app exited with code -1073741819*/
view->load(QUrl("../b.html"));
}
}
}
2、使用linkClicked訊號前必須調用setLinkDelegationPolicy:
page->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
connect(page, SIGNAL(linkClicked(QUrl)), this, SLOT(parseURL(QUrl)));
轉載請註明出處:http://blog.csdn.net/footman_/article/details/6694161
目錄
1 Qt和Javascript互動的兩種方式
2 執行個體分析
2.1 前端——HTML和Javascript
2.2 後台——Qt
3 小結
4 附錄
1 Qt和Javascript互動的兩種方式
為了充分發揮Javascript的跨平台特性,Qt和JavaScript互動將不採用“Qt對Javascript公開對象引用”的方式(即通過QWebFrame的addToJavaScriptWindowObject方法向Javascript提供對象引用)。這種方式雖然使得Qt和JavaScript能直接的互動,但是Javascript端對於Qt端的依賴將影響Javascript發揮跨平台性。該方式調用原理1-1中左圖所示:
圖1-1
不難看出,左邊的方式中Javascript對Qt對象的依賴不利於Javascript往其它平台移植。
而右邊的“自訂URL”方式則不一樣,Javascript不再選擇利用Qt對象去調用Qt方法,而是直接向Webkit瀏覽器發送自訂URL,Webkit捕獲到URL後通過QWebKit自身提供的Signal來關聯Qt中的Slots函數,並向Slots函數傳遞URL,Slots函數就可以根據URL中的資訊作出相應處理。在“自訂URL”方式中,底層平台不論是Qt,還是Android,上層的Javascript只需發送“自訂URL”即可。這樣Javascript的平台無關性就能得以充分發揮。1-2所示:
圖1-2
2執行個體分析
對“自訂URL”方式有了初步認識後,下面通過一個執行個體來敘述這種“自訂URL”的方式中可能涉及到的技術點。
2.1 前端——HTML和Javascript
例子中涉及2個html檔案a.html、b.html和一個Javascript檔案js.js。檔案b.html很簡單,就是一句歡迎語,檔案a.html運行2-1所示:
圖2-1
其對應的代碼如下:
<html>
<script language="JavaScript" type="text/javascript" src="js.js"></script>
<body>
<center>
<span>text a:</span>
<input type="text" name="aText" id="aText" />
<input type="submit" value="Go" onclick="javascript:sendURL()" />
<a href="b.html">b.html</a>
<font color=red><div id=warning></div></font>
</center>
</body>
</html>
該html檔案中引用到的js.js代碼如下:
function sendURL()
{
var value = document.getElementById("aText").value.replace(/\s/g,"");
if(value != "")
{
if(confirm("Go to " + value +"?"))
{
location.href = value;
}
}
else
{
document.getElementById("warning").innerHTML = "Please Input Target";
}
}
2.2 後台——Qt
從a.html和js.js端的代碼不難看出,當使用者在a.html頁面上文字框內輸入內容後,點擊“Go”按鈕就會觸發js.js中的sendURL方法,該方法會把使用者在文字框內輸入的內容當作URL發送,那麼背景Qt端如何得到這個URL呢?
2.2.1 loadStarted訊號
通過查閱Qt協助文檔找到這樣一個訊號——loadStarted(),該訊號在QWebView、QWebPage和QWebFrame均存在。當開始載入一個新的網頁時產生該訊號,所以接收Javascript產生的URL可以嘗試從該訊號入手。
2.2.2 requestedUrl函數
QWebFrame有個方法叫做requestedUrl()。當產生URL請求而載入Web頁面時,調用該方法能過擷取到請求的URL。看來接收Javascript產生的URL,這個方法不可或缺。
2.2.3 擷取URL
下面結合前面選擇的訊號和方法來擷取Javascript產生的URL。
1、為loadStarted訊號設定Slots函數
QWebPage * page = view->page();
connect(page, SIGNAL(loadStarted()), this, SLOT(doLoad()));
2、接收URL
void MyMainWindows::doLoad()
{
QUrl url = view->page()->mainFrame()->requestedUrl();
qDebug()<<"doLoad...."<<url;
/*解析URL*/
parseURL(url);
}
parseURL的具體實現參見附錄。
2.2.4 示範執行個體
接收成功後,就可以由Qt解析URL,由URL中的資訊來選擇應該執行什麼操作。
在本例子中,如果URL是字串“print”,那麼就調用“print”相關模組(簡單的輸出資訊,然後跳轉到b.html頁面)。圖2-2為執行個體運行後的主介面:
圖2-2
輸入print,點擊“Go”按鈕,介面切換,2-3所示:
圖2-3
同時觀察控制台輸出,2-4所示:
圖2-4
從輸出資訊中可以看出,接收到的URL為檔案絕對路徑,解析後比較URL,如果等於“print”,那麼就執行“Call Moudle Of Print”,並載入b.html。
注意,載入b.html頁面時同樣會因為產生loadStarted訊號而執行預先設定好的Slots函數。至此示範完畢!
3小結
在小結之前先來看a.html中埋下的一個小伏筆。
在a.html中有個超連結“b.html”,該連結的URL指向b.html頁面,正常情況下點擊該連結就會跳轉到b.html頁面,但為何在本執行個體程式中點擊b.html不會有任何跳轉呢?
這其中的原因在於QWebKit中的linkClicked訊號,當點擊Web頁面中的超連結時就會產生該訊號。本例中為該訊號設定Slots函數,函數中沒有對超連結的URL進行載入,所以點擊超連結後不會產生任何跳轉。類似於linkClicked這樣的訊號還有很多,可以根據不同的需求選擇使用。
對比兩種互動方式,“Qt對Javascript公開對象引用”的方式在Javascript調用Qt的過程中表現得較為直接,而“自訂URL”的互動方式很好地解決了跨平台問題。總之,方案沒有好壞之分,各有所長,根據實際需求選取即可。
4附錄
1、parseURL方法具體實現如下:
void MyMainWindows::parseURL(QUrl url)
{
QString urlStr = url.toString();
qDebug()<<"parseURL...."<<urlStr;
/*
* 因為每次調用load都會觸發loadStarted訊號而執行該方法,
* 所以必須保證load網頁時不會解析URL,否則load不到網頁。
*/
if(urlStr.right(5).operator != (QString(".html")))
{
int len = urlStr.length();
qDebug()<<"urlStr.length():"<<len;
QString ret = urlStr.right(len-24);
qDebug()<<"Start Parse Url:"<<ret;
if(ret.operator==(QString("print")));
{
qDebug()<<"Call Moudle Of Print";
/*如果找不到該url,app exited with code -1073741819*/
view->load(QUrl("../b.html"));
}
}
}
2、使用linkClicked訊號前必須調用setLinkDelegationPolicy:
page->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
connect(page, SIGNAL(linkClicked(QUrl)), this, SLOT(parseURL(QUrl)));