QTとHTMLページの通信を実現

10422 ワード

1.前言最近、C++とWEBのローカルハイブリッドアプリケーション開発モデルが流行しており、個人的にもタグ言語記述のインタフェースがインタフェース開発の発展傾向であると考えている.WPF、JavaFX、もちろんHtmlも欠かせません.Htmlベースのインタフェースは開発効率,移植性ともに優れているため,多くの
現在、QT公式のドキュメントでは、元のWebKitからQtWebEngineに移行する方法について、十分なドキュメントと指導を提供していません.
この文書では、WebKitからQtWebEngineに移行し、C++とHTMLとJSとのインタラクションを実現した経験と例を記録します.
2.QtWebEngineとWebChannelモジュールを使用して、公式に提供されているPortingfromQtWebKittoQtWebEngine--QWebEngineView*view=newQUrl("http://qt-project.org/"));
view->show();
2)
QtオブジェクトでのWebページ要素へのアクセス
//myPluginが指すオブジェクトはHTMLで名前myPluginObjectでアクセス可能
webView->page()->mainFrame()->addToJavaScriptWindowObject("myPluginObject",myPlugin);
//signalEmittedがトリガーされたときにJavaScriptのfunctionToCall関数を呼び出す
webView->page()->mainFrame()->evaluateJavaScript("myPluginObject.signalEmitted.connect(functionToCall);")
公式推奨の使用方法:
方法1:
runJavaScript(const
QString&scriptSource,FunctorOrLambdaresultCallback)
方法2:QtWebChannel方式を使用して、これは公式の推薦方式で、彼はC++とHTML/JSの双方向通信を簡単に実現することができて、同時にC++とHTML/JSのデカップリングを実現して、開発者の分業とシステムの集積を便利にして、後の例を参照します.
3)WebページでQtオブジェクトにアクセス
Webページでは、次のようなJavaScriptコードを使用してQtオブジェクトにアクセスできます.
クリックしてQtオブジェクトにアクセス
公式推奨の使用方法:
QtWebChannel方式を使用して、これは公式の推薦方式で、彼はC++とHTML/JSの双方向通信を簡単に実現することができて、同時にC++とHTML/JSのデカップリングを実現して、開発者の分業とシステムの集積を便利にして、後の例を参照してください.
QT 5.5とQT 5.6では、QtのQtWebEngineとWebChannelモジュールを利用して、ローカルデスクトップとwebの混合アプリケーションの開発を完全に行うことができ、JavaScript、スタイルシート、Webコンテンツ、Qtコンポーネントを自由に混合することができます.QML/C++とHTML/Javascriptとの間の簡単で使いやすいブリッジを提供するChromiumベースのQtWebChannelモジュールは、QtとWeb技術を組み合わせて開発できるようにしています.現在、QT公式では、QtWebChannelでC++とHTMLをブリッジすることも推奨されています.Qtを参照してください.
WebChannel–bridgingthegapbetweenC++/QMLandtheweb------
まず、信号とスロットを実現するC++とJSの間で伝達するためのdocumentオブジェクトを定義します.
Document.h内容:
#ifndefDOCUMENT_H
#defineDOCUMENT_H
 
  
#include
#include
#include"ui_mainwidget.h"
 
  
namespaceUi{
classMainWidget;
}
 
  
classDocument:publicQObject
{
Q_OBJECT
Q_PROPERTY(QStringtextMEMBERs_textNOTIFYsendText)
 
  
public:
explicitDocument(QObject*parent=nullptr):QObject(parent){}
 
  
voidsetSendTextText(constQString&text);
voidsetUi(Ui::MainWidget*ui);
 
  
publicslots:
voidreceiveText(constQString&r_text);
 
  
signals:
voidsendText(constQString&text);
 
  
private:
voiddisplayMessage(constQString&message);
QStrings_text;
QStringrecieve_text;
Ui::MainWidget*mainUi;
};
 
  
#endif//DOCUMENT_H

Document.cpp内容:
#include"document.h"
 
  
voidDocument::setSendTextText(constQString&text)
{
s_text=text;
emitsendText(s_text);
}
 
  
voidDocument::displayMessage(constQString&message)
{
mainUi->editor->appendPlainText(message);
}
 
  
/*!
ThisslotisinvokedfromtheHTMLclientsideandthetextdisplayedontheserverside.
*/
voidDocument::receiveText(constQString&r_text)
{
displayMessage(QObject::tr("Receivedmessage:%1").arg(r_text));
}
 
  
voidDocument::setUi(Ui::MainWidget*ui)
{
mainUi=ui;

}
QTDesignerでメインインタフェースを設計し、メインインタフェースMainWidgetクラスを実現します.内容は以下の通りです.
mainwidget.h内容:
#ifndefMAINWIDGET_H
#defineMAINWIDGET_H
 
  
#include"document.h"
 
  
#include
#include
 
  
namespaceUi{
classMainWidget;
}
 
  
classMainWidget:publicQWidget
{
Q_OBJECT
 
  
public:
explicitMainWidget(QWidget*parent=0);
~MainWidget();
 
  
//publicQ_SLOTS:
//voidsetEnabled(bool);
 
  
privateslots:
voidon_pushButton_clicked();
 
  
private:
boolisModified()const;
 
  
Ui::MainWidget*ui;
Documentm_content;
 
  
};
 
  
#endif//MAINWIDGET_H

mainwidget.cpp内容:
#include"mainwidget.h"
#include"ui_mainwidget.h"
#include"previewpage.h"
#include"document.h"
 
  
#include
#include
 
  
MainWidget::MainWidget(QWidget*parent):
QWidget(parent),
ui(newUi::MainWidget)
{
ui->setupUi(this);
 
  
PreviewPage*page=newPreviewPage(this);
ui->preview->setPage(page);
m_content.setUi(ui);
 
  
QWebChannel*channel=newQWebChannel(this);
channel->registerObject(QStringLiteral("content"),&m_content);
page->setWebChannel(channel);
 
  
ui->preview->setUrl(QUrl("qrc:/index.html"));
 
  
ui->editor->setPlainText("hello...
");
}
 
  
MainWidget::~MainWidget()
{
deleteui;
}
 
  
boolMainWidget::isModified()const
{
returnui->editor->document()->isModified();
}
 
  
voidMainWidget::on_pushButton_clicked()
{
 
  
m_content.setSendTextText(ui->lineEdit->text());
 
  
}

HTMLページをロードするためのPreviewPageクラスを定義し、メインインタフェースMainWidgetクラスが初期化されると、メインインタフェースのWebEngineViewをインスタンスオブジェクトに初期化します.主な初期化コードは次のとおりです.
PreviewPage*page=newPreviewPage(this);//インスタンスオブジェクトの作成
ui->preview->setPage(page);//メインインタフェースへのオブジェクトの設定
ui->preview->setUrl(QUrl("qrc:/index.html"));//読み込んだHTMLページの設定
previewpage.h内容:
#ifndefPREVIEWPAGE_H
#definePREVIEWPAGE_H
 
  
#include
 
  
classPreviewPage:publicQWebEnginePage
{
Q_OBJECT
public:
explicitPreviewPage(QObject*parent=nullptr):QWebEnginePage(parent){}
 
  
protected:
boolacceptNavigationRequest(constQUrl&url,NavigationTypetype,boolisMainFrame);
};
 
  
#endif//PREVIEWPAGE_H

previewpage.cpp内容:
#include"previewpage.h"
#include
boolPreviewPage::acceptNavigationRequest(constQUrl&url,
QWebEnginePage::NavigationType/*type*/,
bool/*isMainFrame*/)
{
//Onlyallowqrc:/index.html.
if(url.scheme()==QString("qrc"))
returntrue;
QDesktopServices::openUrl(url);
returnfalse;
}
使用するウェブページindex.htmlの内容は以下の通りです:/strong>html
>
//BEGINSETUP
functionoutput(message)
{
varoutput=document.getElementById("output");
output.innerHTML=output.innerHTML+message+"";
}
window.οnlοad=function(){
output("settingupQWebChannel.");
newQWebChannel(qt.webChannelTransport,function(channel){
//makedialogobjectaccessibleglobally
varcontent=channel.objects.content;
document.getElementById("send").οnclick=function(){
varinput=document.getElementById("input");
vartext=input.value;
if(!text){
return;
}
output("Sentmessage:"+text);
input.value="";
content.receiveText(text);
}
content.sendText.connect(function(message){
output("Receivedmessage:"+message);
});
content.receiveText("Clientconnected,readytosend/receivemessages!");
output("ConnectedtoWebChannel,readytosend/receivemessages!");
});
}
//ENDSETUP
html{
height:100%;
width:100%;
}
#input{
width:400px;
margin:010px00;
}
#send{
width:90px;
margin:0;
}
#output{
width:500px;
height:300px;
}
メインプログラムcppの内容は以下の通りです.
#include"document.h"
#include"mainwidget.h"
#include
intmain(intargc,char*argv[])
{
QApplicationa(argc,argv);
MainWidgetw;
w.show();
returna.exec();
}