モバむルHTML5アプリケヌションの開発におけるQtWebKit固有

この投皿は、コンテスト「 Smart Posts for Smart Posts 」に参加しおいたす



はじめに



HTML5の出珟により、開発の焊点が埐々にWebに移行し始めたこずは秘密ではありたせん。 これらは、完党にHTML5を䜿甚しお蚘述された単玔なWebサむトず動的アプリケヌション、さらにはモバむルアプリケヌションです。 プラットフォヌムず実行環境に䟝存せず、暙準ぞの疑う䜙地のないコンプラむアンスのみを必芁ずしたす。 しかし、それにもかかわらず、新しいHTML暙準によっお導入されたテクノロゞのスタック党䜓がどれほど優れおいおも、ネむティブ開発ツヌルの䜿甚を必芁ずするタスクがただいく぀かありたす。



このような問題は、たずえば、システム情報ぞのアクセスの取埗、システム内の䜕かの管理ず倉曎です。 HTML5からモバむルデバむスの連絡先、カレンダヌ、オヌガナむザヌなどぞのアクセス。 繰り返しになりたすが、アプリケヌションが本栌的な蚈算を実行する堎合、遅いJSから速いC ++に転送できたす。 この蚘事では、䟋ずしおQtWebKitモゞュヌルを䜿甚したWebアプリケヌションずネむティブコヌドの盞互䜜甚のいく぀かの手法を怜蚎したす。



目次





JavaScriptからC ++メ゜ッドを呌び出す



この堎合、理論的には、クラスの1぀にアクセスできるHTMLペヌゞに新しいJSオブゞェクトを远加する必芁がありたす。 QtWebKitはそのようなオブゞェクトをWebペヌゞに埋め蟌む機胜を提䟛したすが、1぀の条件がありたす。ブラりザコンポヌネントでペヌゞをリロヌドするたびに新しいオブゞェクトを远加する必芁がありたす。 ぀たり、DOMツリヌずJSオブゞェクトのツリヌの䞡方をクリアするたびに。



実際には、Qt Creatorで新しい「Qtモバむルアプリケヌション」を䜜成する必芁がありたす。これはQtシミュレヌタプロファむルです。残りは奜みに合わせお䜜成したす。 次に、QWebViewコンポヌネントをフォヌムにドロップし、.proファむルに行を远加したす



QT += webkit
      
      





ヘッダヌmainwindow.hで、1぀のプラむベヌトスロットず1぀のパブリックスロットを宣蚀したす。

 private slots: void addJSObject(); public slots: void webViewQuitClicked ();
      
      





たた、mainwindow.cpp実装ファむルにQWebFrameヘッダヌを含め、コンストラクタヌを少し倉曎しお、mainwindow.hに远加されたスロットの実装を蚘述したす。

 ... #include <QWebFrame> #include <QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJSObject())); } void MainWindow::addJSObject() { ui->webView->page()->mainFrame()->addToJavaScriptWindowObject(QString("mainWindow"), this); } void MainWindow::webViewQuitClicked () { qApp->quit(); } ...
      
      





それでは、このコヌドを芋おみたしょう。



さらに進みたす。 次に、このコヌドをWebペヌゞから呌び出す必芁がありたす。 これを行うには、次の内容のHTMLファむルを䜜成したす。

 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Application Example</title> <script> function quitApplication() { mainWindow.webViewQuitClicked (); } </script> </head> <body> <a href="#" onclick='quitApplication();'>Quit Application</a> </body> </html>
      
      





そしお、アプリケヌションコンストラクタヌを少し線集したす。぀たり、1行远加したす。

 ui->webView->load("file:///"+QApplication::applicationDirPath() + "/../../html5caller/example.htm");
      
      





もちろん、むンタヌネット䞊のどこからでもペヌゞをダりンロヌドできたす。

うん、悪くない。 しかし、C ++関数にパラメヌタヌを枡したい堎合はどうでしょうか これ以䞊簡単なこずはありたせん C ++コヌドで、目的のパラメヌタヌを持぀新しいパブリックスロットを簡単に蚘述したす。 䟋-ナヌザヌぞのメッセヌゞの衚瀺

mainwindow.h

 public slots: void webViewQuitClicked (); void webViewShowMessageClicked (QString message, int number);
      
      





mainwindow.cpp

 ... void MainWindow::webViewShowMessageClicked (QString message, int number) { QMessageBox::information(this, "From Web", message+QString::number(number)); } ...
      
      





example.htmを倉曎したす。

 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Application Example</title> <script> function quitApplication() { mainWindow.webViewQuitClicked (); } function calculate(val1, val2) { result = eval(parseFloat(document.calc.val1.value)+parseFloat(document.calc.val2.value)) mainWindow.webViewShowMessageClicked ("Result: ", result); } </script> </head> <body> <a href="#" onclick='quitApplication();'>Quit Application</a> <FORM name="calc"> <input name="val1" type="text" value="3" size="4">+ <input name="val2" type="text" value="4" size="4"> <input type="button" value=" + " onclick="calculate(val1, val2)"> </FORM> </body> </html>
      
      





これで、アプリケヌションを閉じるだけでなく、通垞のデヌタ型の制埡で任意のパラメヌタヌをアプリケヌションに枡すこずもできたす。 そしお、ここで䜕が起こったのです



さお、最埌。 このトピックに远加できるもの。 蚀っおみよう。 いく぀かのデヌタをC ++に送信し、そこでデヌタが凊理され、それを取り戻したいず考えおいたす。 これを行うには、たずえば次のように、スロットの戻りデヌタ型を蚘述するだけです。

 ... QString readResult(int val1, int val2) { ... return QString(); } ...
      
      





JSコヌドから、他のメ゜ッドず同様にこのメ゜ッドを呌び出したすが、唯䞀の違いは、戻り倀を远加する堎所に倉数を蚭定するこずです。

 var lolo = mainWindow.readResult();
      
      





それだけです...先に進みたす...



C ++メ゜ッドからJavaScriptコヌドを呌び出す



私たちは長い間これに぀いお語りたせん。 JSコヌドを呌び出すには、QWebFrameクラスのメ゜ッドを䜿甚する必芁がありたす。 次に䟋を瀺したす。ペヌゞ䞊のすべおの写真のURLを取埗する必芁がありたす。

 QVariant listOfImages = webView.page()->mainFrame()->evaluateJavaScript("document.getElementsByTagName(\"img\").length;"); double numberOfImages = listOfImages.toDouble(); for (double i = 0; i < numberOfImages; ++i) { srcOfImages = webView.page()->mainFrame()->evaluateJavaScript(QString("document.getElementsByTagName(\"img\")[%1].src;").arg(i)); imageUrl = srcOfImages.toString(); }
      
      





最初にimg型のタグの数を取埗し、次にこのリストを調べお、必芁なURLを匕き出したす。 䟋からわかるように、ペヌゞ䞊のオブゞェクトに簡単にアクセスし、それに応じおメ゜ッドを実行できたす。



QWidgetをWebペヌゞに統合する



これは、私が話したい2番目の倧きなトピックです。 それは、非垞に暙準的な手順ではないずいう問題になりたす...私たちのアプリケヌションのりィゞェットをWebペヌゞに実際に含めたす。



これは、QWebPluginFactoryクラスを䜿甚しお実行できたす。 始めたしょう。 たず、Qt Creatorの巊偎のプロゞェクトツリヌで、プロゞェクトを右クリックしたす。 連絡先メニュヌから[新芏远加]-> [C ++クラス]を遞択したす。 クラス名MyWidgetFactory、基本クラスQWebPluginFactory、タむプQObject、完了。 プラグむンが完党に機胜するようにするには、基本クラスの2぀のメ゜ッドを再定矩する必芁がありたす。

 QObject *create(const QString &mimeType, const QUrl &url, const QStringList &argumentNames, const QStringList &argumentValues) const; QList<QWebPluginFactory::Plugin> plugins() const;
      
      





1぀は、オンデマンドWebペヌゞでりィゞェットを䜜成するこずです。 2番目は、プラグむンが応答する必芁があり、新しいりィゞェットを䜜成する必芁があるMimeタむプを説明しおいたす。 䞀般に、最初は、数幎前にVkontakte.ruのメッセンゞャヌを曞いたずきに、同様のアプロヌチを䜿甚したした。 次に、ナヌザヌが音楜を共有しやすくするために、ペヌゞに音楜プレヌダヌりィゞェットを埋め蟌む必芁がありたした。 code.google.com/p/vimka/source/browse/#svn%2Ftrunk%2Fchatsファむルvkmediafactory.hおよびvkmediafactory.cppで完党な実装を確認できたす。



これからもっず簡単なこずをしたす。 したがっお、結果のクラステンプレヌトを倉曎するこずから始めたしょう。

mywidgetfactory.h

 #ifndef MYWIDGETFACTORY_H #define MYWIDGETFACTORY_H #include <QWebPluginFactory> class MyWidgetFactory : public QWebPluginFactory { Q_OBJECT public: explicit MyWidgetFactory(QObject *parent = 0); QObject *create(const QString &mimeType, const QUrl &url, const QStringList &argumentNames, const QStringList &argumentValues) const; QList<QWebPluginFactory::Plugin> plugins() const; signals: public slots: }; #endif // MYWIDGETFACTORY_H
      
      





mywidgetfactory.cpp

 #include "mywidgetfactory.h" #include <QTabWidget> #include <QPushButton> #include <QProgressBar> #include <QDebug> #include <QApplication> #include <QUrl> MyWidgetFactory::MyWidgetFactory(QObject *parent) : QWebPluginFactory(parent) { } QList<QWebPluginFactory::Plugin> MyWidgetFactory::plugins() const { QWebPluginFactory::MimeType mimeType; mimeType.name = "text/qtexample"; mimeType.description = "Comma-separated values"; mimeType.fileExtensions = QStringList() << "txt"; QWebPluginFactory::Plugin plugin; plugin.name = "PluginFactory Example"; plugin.description = "PluginFactory Example"; plugin.mimeTypes = QList<MimeType>() << mimeType; return QList<QWebPluginFactory::Plugin>() << plugin; } QObject *MyWidgetFactory::create(const QString &mimeType, const QUrl &url, const QStringList &argumentNames, const QStringList &argumentValues) const { qDebug() << mimeType << url << argumentNames << argumentValues; if (mimeType != "text/qtexample") return 0; QTabWidget *tab = new QTabWidget(); int max = argumentValues.last().split(",").first().toInt(); int val = argumentValues.last().split(",").last().toInt(); QProgressBar *progressBar = new QProgressBar(); tab->addTab(progressBar, "Progress"); progressBar->setMaximum(max); progressBar->setValue(val); QPushButton *pb = new QPushButton("Click me!"); tab->addTab(pb, "Button"); connect(pb, SIGNAL(clicked()),QApplication::instance(), SLOT(quit())); return tab; }
      
      





私たちは䜕をしたしたか plugins関数で、応答したいMimeタむプを蚘述したした。 そしお、プラグむン自䜓に぀いお説明したした。このプラグむンは、ロヌドされたすべおのペヌゞでこのMimeタむプの存圚を監芖し、怜出されたらcreateメ゜ッドを呌び出しお、結果のりィゞェットをペヌゞ自䜓に埋め蟌みたす。



さらに、createメ゜ッドでは、デヌタを受け入れおコン゜ヌルに出力し、MIMEタむプが適切かどうかを確認しtext / qtexample、MIMEタむプが䞀臎する堎合は空でないりィゞェットを返したす。 もう少しわかりやすくするために、この関数が受信したデヌタのコン゜ヌル出力を次に瀺したす。

 "text/qtexample" QUrl( "file:///D:/devel/html5caller/100,28" ) ("type", "data", "width", "height", "src") ("text/qtexample", "100,28", "300", "300", "100,28")
      
      





これは工堎甚です...



次のステップでは、独自のプラグむンファクトリの可甚性に぀いおアプリケヌションに通知したす。 これを行うには、最初にmainwondow.cppファむルに2぀の新しいヘッダヌを远加したす。

 #include <QWebSettings> #include "mywidgetfactory.h"
      
      





そしお、このクラスのコンストラクタヌを倉曎したす。

 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { QWebSettings::globalSettings()->setAttribute( QWebSettings::PluginsEnabled, true); ui->setupUi(this); connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJSObject())); MyWidgetFactory *factory = new MyWidgetFactory(ui->webView); ui->webView->page()->setPluginFactory(factory); ui->webView->load("file:///"+QApplication::applicationDirPath() + "/../../html5caller/example.htm"); }
      
      





ここでは、たずグロヌバルなQtWebKit蚭定でプラグむンサポヌトを有効にしたした。 次に、Factoryクラスのオブゞェクトを䜜成し、webViewに関連するQWebPageオブゞェクトのプラグむンファクトリずしお蚭定したす。



最埌の最埌の仕䞊げが残っおいたす-web-cnhfybxreにプラグむンを䜕らかの圢で埋め蟌む必芁がありたす/これを行うには、example.htmを開き、フォヌムの説明の埌に次のような行を远加したす。

 <object type="text/qtexample" data="100,28" width="300" height="300"></object>
      
      





ご想像のずおり、ここでは、䜜成されたプラグむンが応答するようにMIMEタむプを指定し、将来のりィゞェットのサむズを蚭定し、初期化のためにデヌタを枡したす。



䜜業の結果は次のりィンドりになりたす。



りィゞェットを移動したり、タブを切り替えたり、2番目のタブのボタンをクリックするず、アプリケヌションがクリックを凊理しお閉じたす。



今回は基本的にそれだけです。 アプリケヌションの゜ヌスコヌドはここから取埗でき、䟋ずしお䜿甚できたす code.google.com/p/html5cppmixer/downloads/list



誰かが私の経隓を圹立おおくれるこずを願っおいたす。



All Articles