Qt與JS(三)

 

Qt不錯的學習網址:javascript

http://www.cnblogs.com/findumars/p/5529526.htmlhtml

 

----------------------------------------------------java

IE內核,qt調用js;qt寫com組件,html就能夠調用qtweb

能夠百度 QAxBindable  會搜索到比較有用的文章瀏覽器

http://blog.csdn.net/csxiaoshui/article/details/47333989安全

http://blog.csdn.net/csxiaoshui/article/details/48000885app

http://blog.csdn.net/csxiaoshui/article/details/50735018less

http://blog.csdn.net/jxd9955/article/details/30260725函數

ui->axWidget->setControl("Shell.Explorer");
 
ui->axWidget->setObjectName(QString::fromUtf8("WebBrowser"));
ui->axWidget->setFocusPolicy(Qt::StrongFocus);
//去邊框
ui->axWidget->setWindowFlags(Qt::FramelessWindowHint);
ui->axWidget->setStyleSheet("QGraphicsView{border:0px;}");
 
 
ui->axWidget->dynamicCall("Navigate(constQString&)",QString("file:///D:/proj/m5/m5/baidu_map_new.html"));
 
IWebBrowser2*webBrowser=0;
 
ui->axWidget->queryInterface(IID_IWebBrowser2,(void**)&webBrowser);
 
if(webBrowser)
{
VARIANT_BOOLresult;
HRESULTbusy=webBrowser->get_Busy(&result);
 
if(VARIANT_TRUE==result)
{
 
}
}
 
ui->axWidget->close();

 

ui->axWidget->show();

+++++++++++++++++++++++++++++++++++++++++++
調用js函數
voidMainWindow::SetLocation(std::wstringx,std::wstringy,std::wstringstr)
{
if(QString::fromStdWString(x).trimmed().isEmpty()||
QString::fromStdWString(y).trimmed().isEmpty())
{
QMessageBox::information(this,QString("NOTICE"),
#ifdefENGLISH_
QString("Targetaddressisempty!"));
#else
QString("目標地址爲空!"));
#endif//ENGLISH_
 
return;
}
 
QAxObject*document=ui->axWidget->querySubObject("Document");
IHTMLDocument2*doc2;
if(document!=NULL)
{
document->queryInterface(QUuid(IID_IHTMLDocument2),(void**)&doc2);
}
 
if(doc2)
{
IHTMLWindow2*win2=NULL;
if(doc2->get_parentWindow(&win2)==S_OK)
{
WCHARlocationInfo[MAX_PATH]={0};
wsprintf(locationInfo,L"setLocation(%s,%s,%s)",x.c_str(),y.c_str(),str.c_str());
 
BSTRs1=SysAllocString(locationInfo);
BSTRs2=SysAllocString(L"JavaScript");
VARIANTret;
if(win2!=NULL)
{
win2->execScript(s1,s2,&ret);
}
 
SysFreeString(s2);
SysFreeString(s1);
}
}
}
 

 

------------------------------------------------------------------------------post

QT5 與JS交互不錯的文章:

http://blog.csdn.net/d7185540/article/details/52896531

http://blog.csdn.net/sharetm/article/details/55260207

---------------------------------------------------------------------------

Qt之QtScript(一)

http://blog.csdn.net/liuhongwei123888/article/details/6162159

http://blog.csdn.net/styyzxjq2009/article/details/8364545

-----------------------------------------------------------------------------------

WebView與JS

這種用法不多見:

http://www.cnblogs.com/ziqiuqiandao/archive/2012/12/29/2838652.html

能夠獲取到html元素的值:

  1.     QWebFrame *frame = ui->webView->page()->mainFrame();  
  2.     QWebElement userNameEle = frame->findFirstElement("#userName");  
  3.     QWebElement passwordEle = frame->findFirstElement("#password");  
  4.     QString userName = userNameEle.evaluateJavaScript("this.value").toString();  
  5.     QString password = passwordEle.evaluateJavaScript("this.value").toString();

http://blog.csdn.net/liuhongwei123888/article/details/6137094

 

 

 

 

 

QT分析之WebKit http://www.cnblogs.com/lfsblack/p/5278777.html 對WebKit進行了詳細的講解,

 http://www.cnblogs.com/findumars/p/5529526.html能夠將QT的屬性值暴露給html文件。

大衆用法:

QString strFunc(tr("locateCity('南京', 11);"));

m_pWebView->page()->mainFrame()->evaluateJavaScript(strFunc);

 

幾個注意點:

QWebView爲什麼有些網頁顯示不了:

一、網頁是https協議的,使用SSL加密鏈接了。你的Qt庫集成了openssl模塊嗎?若是沒有,要-openssl開關重編QtNetwork庫。若是有,鏈接webView->page()->networkAccessManager()的sslErrors信號,調用QNetworkReply的ignoreSslErrors函數,而後把libeay32.dll和ssleay32.dll兩個文件和程序放到一塊兒。

二、把 qt-create中的 ssleay32.dll 和 libeay32.dll 複製到 qt sdk的 bin目錄下面

在學習Qt,作了個瀏覽器demo,沒搞懂對https是怎麼支持的?我開發的時候用的機器全部https網站都正常顯示,後來拿到另外一臺機器上,全是空白頁。網上有說是ssl握手產生錯誤的問題,我把代碼搞到後一臺機子上寫了發現仍是不行,根本沒收到sslerror的signal。用其它瀏覽器都是正常打開,不明白爲何?

是否是libeay32.dll和ssleay32.dll缺了?

是由於這2個dll,可是電腦裏是有的,其餘程序都能找到這個路徑就是我本身搞的不行,後來把openssl一塊兒打包了。

QWebView直接load能夠打開https網頁,網頁內的大多數的按鈕點擊卻無反應
NetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData)裏能夠看到有請求返回,
但WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)卻收不到請求。

一、

有沒有試過調用QWebPager的setLinkDelegationPolicy函數,我以前有碰到過點擊連接不處理的問題,是由於沒有調用這個函數。
ui->webView->page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);

三、實在不行,參考方案:最終仍是QT整合MFC的CHtmlView來作

 

    /* 開啓JavaScript支持 */  好像不是必須的!!

    QWebSettings *pWebSettings = m_pWebView->page()->settings();

 

    pWebSettings->setAttribute(QWebSettings::JavascriptEnabled,true);

 

 

    /* 創建信號與槽, 每次載入html時發送段信號 */  必需要!!!

    connect(m_pWebView->page()->mainFrame(),SIGNAL(javaScriptWindowObjectCleared()),

            this,SLOT(addObjectToJs()));

 

Qt代碼裏先嚐試在javaScriptWindowObjectCleared信號對應的槽裏調用,結果失敗了:

connect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
            this, SLOT(populateJavaScriptWindowObject()));
...
void FormExtractor::populateJavaScriptWindowObject()
{
    ui.webView->page()->mainFrame()->evaluateJavaScript("tryalert();");
}

 

 

是由於這個信號發出得太早了,頁面尚未徹底載入。須要在後面調用。最好是響應loadFinished(bool)信號:
connect(ui.webView->page()->mainFrame(), SIGNAL(loadFinished(bool)),
            this, SLOT(callFunction()));
...
void FormExtractor::callFunction()
{
    ui.webView->page()->mainFrame()->evaluateJavaScript("tryalert();");
}

QWebview控件

該控件是用於在Qt中顯示網頁的控件,通常而言會將contextMenuPolicy屬性設置爲NoContextMenu隱藏系統爲其提供的默認右鍵菜單

<1>. 加載網頁:

1
2
3
ui->webViewCut->load(QUrl( "http://www.baidu.com" ));
//若是是本地網頁,必須使用file:///的前綴做爲網頁地址
ui->webViewCut->load(QUrl( "file:///c:/test.html " ));

<2>. Qt代碼中調用QWebview加載的網頁中的js函數:

1
2
3
4
5
6
7
8
9
10
//先做以下設置
ui->webViewCut->page()->setForwardUnsupportedContent( true );
ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled,  true );
ui->webViewCut->page()->settings()->setAttribute(QWebSettings::PluginsEnabled,  true );
ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavaEnabled,  true );
ui->webViewCut->page()->settings()->setAttribute(QWebSettings::AutoLoadImages,  true );
 
//而後在QWebview的loadFinished槽函數中調用js,該槽函數表示網頁已經加載完畢
QString js = QString( "alert(\'hello Qt!\')" );
ui->webViewCut->page()->mainFrame()->evaluateJavaScript(js);

<3>. 在QWebview加載的html的js代碼中調用Qt的函數:

默認狀況下在QwebViewCut中的網頁裏面的js不能直接調用Qt中的相關功能,這涉及到安全性問題。要知足js中調用Qt的功能必須知足下面的條件:

在Qt中暴露一個對象給js,而後js就能夠在網頁中直接使用這個對象以及該對象的[特定]函數,要求是被暴露Qt對象必須繼承自QObject類,而且在js中調用這個暴露的對象的成員函數的定義是有要求的,該對象的知足下面的要求的成員函數均可以直接被js調用:

1.必須是該對象的公共函數,而且在函數聲明前面添加Q_INVOKABLE修飾,例如:

1
2
public  :
  Q_INVOKABLE  int  TestQt();

2.若是該函數被聲明成一個public slot 也能夠不添加Q_INVOKABLE修飾:

1
2
public  slots:
   void  TestQt();

我的認爲第一種方法更好,由於能夠設置返回值,而Qt的槽函數是沒有返回值的,都是返回void,只須要調用this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj", this); 就能夠將一個Qt對象,也就是這裏傳遞的this表明的對象,固然也能夠直接傳遞其餘對象指針,暴露給網頁中的javascript,網頁中的javascript在調用的時候能夠直接使用 QtObj 去引用咱們的Qt對象,以及經過QtObj去直接調用符合條件的Qt對象的成員函數。

那麼this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj", this);代碼在何時執行呢? 推薦是在QWebFrame的信號javaScriptWindowObjectCleared發出的時候執行,因此咱們能夠在當前UI界面類的構造函數中添加下面的代碼:

1
2
connect(ui->webViewCut->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
     this , SLOT(populateJavaScriptWindowObject()));

而後在處理javaScriptWindowObjectCleared()信號的槽函數中實現上述暴露功能:

1
2
3
4
void  MainWindow::populateJavaScriptWindowObject()
{
    ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject( "QtObj" this );
}

根據Qt文檔上對該信號的描述javaScriptWindowObjectCleared()這個信號會在咱們調用QwebViewCut::load()加載新的url以前就觸發,咱們在這個時候去處理這個信號,將咱們須要暴露的Qt對象暴露給即將載入的網頁

<4>. 將Qt的屬性暴露出去供js調用,使用以下方法:

1
Q_PROPERTY( int  Qtvalue READ testValue WRITE setTestValue)

將上面的語句加入到類的聲明中,在private塊下面就能夠,最後不須要以分號結尾,例如:

1
2
private :
  Q_PROPERTY( int  Qtvalue READ testValue WRITE setTestValue)

這一行的做用是將屬性 Qtvalue 註冊到Qt的元對象系統中,在js中能夠經過名字Qtvalue來訪問該屬性,但在js中訪問該屬性的時候假設Qt暴露給js的對象爲QtObj,那麼在js中能夠這樣訪問該屬性:

1
2
QtObj.Qtvalue = 10;  //設置該屬性的時候會調用void setTestValue(int)
alert(QtObj.Qtvalue)  //獲取該屬性的時候會調用 int testValue()

Q_PROPERTY(int Qtvalue READ testValue WRITE setTestValue)的結構以下:

1
2
Q_PROPERTY( 類型   屬性名    READ     返回屬性值的函數    WRITE     設置屬性值的函數 )
             int    Qtvalue            int  testValue()           void  setTestValue( int )

也就是說在js中咱們能夠直接使用Qtvalue,當獲取Qtvalue的值的時候會自動調用暴露對象的 int testValue() 函數 ,Qt規定其返回值必須與Q_PROPERTY語句中指定的類型相同,而且必須沒有參數。當咱們爲Qtvalue設置值的時候會調用暴露對象的void setTestValue(int)函數,該函數必須有一個int類型的參數(類型也必須與前面Q_PROPERTY語句中指定的類型相同),而且不能有返回值。

通過實驗int testValue()void setTestValue(int)函數的聲明在private區域也能夠,好像無所謂。其實這兩個函數的名字是能夠隨意定的,對js暴露的屬性名是Qtvalue,當訪問Qtvalue屬性的時候,會自動調用Q_PROPERTY聲明中READ後面指定的函數去獲取值,而且調用WRITE後面指定的函數去設置值,而不在意這兩個函數的名字。

另外這兩個函數獲取的值或者設置的值從哪裏得來呢,咱們能夠在Qt對象中定義一個私有變量來保存這個值,而這個私有變量的名字是無所謂的,甚至若是須要的話,咱們也沒必要保存這個值,直接在函數testValue裏面返回一個常量值,也就是說是否應該定義一個私有變量來保存Qtvalue相關聯的屬性值,這個也不是必須的。

更多Qt QWidget與js的交互能夠在Qt文檔中搜索  The Qt WebKit Bridge關鍵字,其實Q_PROPERTY並非專用於暴露屬性給js的,Q_PROPERTY是Qt元對象系統的一部分。

<5>. 若是在QWebview加載的網頁中有Flex應用程序,而且Qt中調用該QWebview加載的網頁中的js函數中須要調用flex程序暴露給js的接口,那麼還須要做以下設置:

"%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\"路徑下新建xxx.cfg文件,將當前flex應用程序所在位置(也就是swf文件所在的目錄)填寫到該文件中便可,該xxx.cfg的名字是無所謂的,隨便什麼名字,在xxx.cfg文件中指定的目錄路徑中的swf文件的運行是被信任的。xxx.cfg文件中能夠指定多個目錄,每行一個。實際上%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\路徑下也能夠有多個文件名不一樣的cfg文件。xxx.cfg文件中指定的目錄實際上能夠直接指定爲根目錄,例如swf文件的路徑是F:/xxx/yyy/zzz/test.swf,那麼咱們新建的xxx.cfg中的內容的第一行能夠直接指定爲F:/便可。

其實FlexBuilder在創建項目的時候,其生成的swf所在的目錄都被添加到了%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\下面的flashbuilder.cfg中了,因此使用FlexBuilder調試項目的時候,運行的swf都是被信任的。

 

 

 

js調用QT時,傳遞參數類型:

註冊:

m_pWebView->page()->mainFrame()->addToJavaScriptWindowObject("m5_js",this);

 

js調用qt的函數

void m5_js::setInfor(const QString a)

{

ui.btadd->setText(a);

 

}

          js函數:  

function attribute() {

var p = marker.getPosition();

var ll = p.lng.toString();

m5_js.setInfor(ll)

//m5_js.setInfor(p.lng.toString())

 //獲取marker的位置

alert("marker的位置是" + p.lng + "," + p.lat);

}

Qt代碼裏先嚐試在javaScriptWindowObjectCleared信號對應的槽裏調用,結果失敗了:

connect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
            this, SLOT(populateJavaScriptWindowObject()));
...
void FormExtractor::populateJavaScriptWindowObject()
{
    ui.webView->page()->mainFrame()->evaluateJavaScript("tryalert();");
}

 

是由於這個信號發出得太早了,頁面尚未徹底載入。須要在後面調用。最好是響應loadFinished(bool)信號:
connect(ui.webView->page()->mainFrame(), SIGNAL(loadFinished(bool)),
            this, SLOT(callFunction()));
...
void FormExtractor::callFunction()
{
    ui.webView->page()->mainFrame()->evaluateJavaScript("tryalert();");
}

相關文章
相關標籤/搜索