ご存知のように、QMLはグラフィックプリミティブに基づいており、簡単なボタンでさえも描画する必要があります(たとえば、長方形、グラデーション、テキスト、マウス領域)。 UIの作成プロセスを容易にするために、Qtコンポーネントが作成されました。 データを入力または表示するためのボタン、テキストフィールド、ドロップボックス、およびその他のコントロールを作成できます。 公式リリースでは、
モバイルプラットフォーム:SymbianおよびMeeGo。 ただし、Qt Labsにはデスクトッププラットフォーム用のバージョンもあり、これは(しばらくして)ユーザーインターフェイスを作成する主な手段としてQt5に含まれます(覚えているように、Qt5でQMLが最初になり、QtGuiが2番目になります)。 同時に、コンポーネント自体はオペレーティングシステムのネイティブな外観に適応します。
デスクトップコンポーネントの機能を示し、同時にそれらの使用の主な問題と利点を概説するために、古典的なQtGuiとコンポーネントで最小限のグラフィカルアプリケーションを作成しました。 いいえ、Hello Worldではありません。 電卓。 計算を実装せずに、グラフィカルインターフェイスのみ。
猫の下で3つのオペレーティングシステムの下で起動し、トピックに関するいくつかの議論が収集されます。
そのため、電卓には、ディスプレイと、異なるボタンを備えた2つのタブが含まれています。上記の簡単なセットと高度なセットです。
最初にコードを扱います。
Qtコンポーネント電卓
コンポーネントを操作するときに知っておくべき最初の最も興味深いことは、コンポーネントがQmlApplicationViewerまたはQDeclarativeViewを明示的に使用しないことです 。 QmlファイルはQDeclarativeEngineを介して起動されます。 そして、コンポーネント自体が、必要なときに(つまり、新しいウィンドウが作成されるときに) QDeclarativeViewを作成します。 作業を容易にするために、 QmlDesktopViewerクラスはコンポーネントリポジトリにあります 。これは、プロジェクトを一般的なソースツリーに接続し、main.cppで使用することで簡単にプロジェクトに接続できます。
#include <QtGui/QApplication> #include "qmldesktopviewer.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QmlDesktopViewer *viewer = new QmlDesktopViewer(); viewer->open("qrc:/main.qml"); QObject::connect(&app, SIGNAL(lastWindowClosed()), viewer, SLOT(quit())); return app.exec(); }
それでは、QMLを見てみましょう。 main.qmlファイルを作成します。このファイルは、アプリケーションの起動時に起動されます
import QtQuick 1.1 import QtDesktop 0.1 Window { function buttonPressed(name, offset) { var text = display.text var pos = display.cursorPosition display.text = text.substr(0,pos) + name + text.substr(pos) display.cursorPosition = pos+name.length-offset } title: "Calc on Components" width: 400 height: 600 maximumHeight: 900 minimumHeight: 250 maximumWidth: 1000 minimumWidth: 300 visible: true id: mainWindow TextField { id: display anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.margins: 4 height: 60; font.pixelSize: 40 } TabFrame { id: frame position: "North" anchors.top: display.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 4 Tab { id: simpleTab title: "Simple" anchors.margins: 4 CalcButtonRow { anchors.left: parent.left anchors.right: parent.right height: parent.height/4 anchors.top: parent.top names: ["7","8","9","+"] onButtonPressed: mainWindow.buttonPressed(name, 0) } // 3 } // } Component.onCompleted: display.focus = true }
ソースを少し減らしましたが、このファイルには合計125行あります。
したがって、ここでの主な要素はWindowです。 すべての要素を表示するQDeclarativeViewを作成するだけです。 ウィンドウの場合、タイトル、高さ、幅、最大および最小の高さと幅、可視性を設定できます。 一般的に、ウィンドウの標準セット。 ウィンドウの最初の要素はディスプレイで、 TextFieldに実装されています 。 誰かがモバイルQtコンポーネントで開発した場合、この要素はおなじみのはずです。 モバイルコンポーネントとほぼ同じAPIを備えています。
次の要素はTabFrameで 、最終的にQTabWidgetに変換されます。 この要素に2つのTab要素を追加します(1つを短縮しましたが、まったく同じです)。 タブの内容全体がこのタブに表示されます(つまり、ウィジェットをタブウィジェットまたはQtGuiのレイアウトに追加することに似ています)。
この場合のCalcButtonRowは、4つのボタン( namesプロパティを介して渡された名前 )を含むコンポーネントであり、ボタンがタブのスペース全体を占めるように幅と高さを引き伸ばします(表示はQtGuiのタブウィジェットのQGridLayoutに相当します)。 解決策は額にあり、本番環境で多くの問題が発生しますが、テストには役立ちます。
import QtQuick 1.0 import QtDesktop 0.1 Item { signal buttonPressed(string name) property variant names: ["","","",""] Button { anchors.left: parent.left anchors.top: parent.top anchors.bottom: parent.bottom width: parent.width/4 text: names[0] onClicked: buttonPressed(text) } // 3 }
ソースコードを再度削減しました(元のコードでは43行)。 サイドボタンは側面に、中央のボタンは親要素の中央に配置されます。 親要素の4分の1幅の4つすべて。
ここでは、モバイルコンポーネントに精通しているはずのButton要素に出会います。 ボタンクリックハンドラーでは、ボタンにテキストが記述された要素から信号を送信します。
main.qmlに戻りましょう
// function buttonPressed(name, offset) { var text = display.text var pos = display.cursorPosition display.text = text.substr(0,pos) + name + text.substr(pos) display.cursorPosition = pos+name.length-offset } // onButtonPressed: mainWindow.buttonPressed(name, 0) // (sin(), cos() ..) onButtonPressed: mainWindow.buttonPressed(name, 1)
ボタンが押されると、 buttonPressed関数が呼び出され、現在のカーソル位置の行にボタンテキストが追加され、必要な文字数だけシフトされます(関数の場合、カーソルは角括弧の中ではなく、角括弧の中にあるため、この数字は1つ少なくなります)。
これは完全なコードです。 合計で、約160のqml行が判明しました。
QtGuiで記述された同様のコード(デザイナーなし、ループ内のコンストラクター内のすべてのオブジェクトの生成、QSignalMapperおよびそのようなフォームのコードを削減する他の方法)は、約130行のc ++コード(main.cppを除く)を取りました。
つまり、コードの量はほぼ同じです。 さまざまなOSで結果を見てみましょう
Linux KDE4
すべてがほぼ同じですが。 ボタン(さまざまなグラデーション)はQMLバージョン、タブレンダリングの小さな枠、青いフォーカスフレームが常に点灯します(ウィンドウがアクティブでない場合はQtGuiバージョンでは消えます)。テキストフィールドにテキストを追加するときやタブを切り替えるときにアニメーションはありません。 悪くない。
Windows 7
QMLバージョンでは、タブが表示された小さな横枠があります。フォーカスフレームは常に表示され、さらに、マウスポインターからのトレースがボタン上にあります(QtGuiバージョンでは、必要に応じて消えます)。 繰り返しますが、悪くはありません。
Mac OS X 10.6
従来、qmlバージョンでは書き込みフォーカスフレームであり、非アクティブなウィンドウに常に書き込みタブが追加されていました。 しかし。 Mac OS Xの場合、QtGuiでアプリケーションを少し修正する必要がありました。初めて起動したとき、ウィンドウは次のように見えたからです。
QLineEditでminimumHeightを明示的に指定する必要がありました。 QMLバージョンはやり直されていません。
QtGuiの代わりにQMLを使用することの利点
QtGuiがある場合、これらのコンポーネントが必要な理由を尋ねます。 答えは簡単です。 より快適でリッチなインターフェイスを作成します。 動的スクロール、オブジェクトを変更するときの美しいアニメーションなど、よく知られている機能については説明しません。
計算機UIには何を追加できますか? 最初に思い浮かぶのは、入力されたテキストの表示に対するフォントサイズの依存関係です。 テキストが多いほど、フォントは小さくなります。 このために、TextFieldの表示を変更します
TextField { function adaptFontSize() { var width = display.width var length = display.text.length var newFontSize = 40 if (width/26 < length) { newFontSize = 1.5*(display.width/display.text.length) if (newFontSize < 20) newFontSize = 20 } display.font.pixelSize = newFontSize } id: display anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.margins: 4 height: 60; font.pixelSize: 40 onWidthChanged: adaptFontSize() onTextChanged: adaptFontSize() Behavior on font.pixelSize { NumberAnimation{easing: Easing.OutElastic; duration: 200}} }
いつものように、QMLの魔法のアクション。 1つの関数、2つのプロパティ変更ハンドラー、およびBehavior要素を追加しました。 それだけです。今では、フォントを動的に変更し、アニメーションも変更しています。 QtGuiコードはどれくらいかかりますか(アニメーションとまったく同じですか)? 15行強。 Animation Frameworkを接続する必要があります。
QMLを使用してデスクトップUIアプリケーションを簡単に作成できる、さらに多くの例を考え出すことができます。
デスクトップのQtコンポーネントの現在の状態
現在、このプロジェクトはアルファエリアのどこかにあり、その広範な商用アプリケーションについて話すのは時期尚早ですが、今では非常にうまく機能し、QtGuiウィジェットをQMLインターフェイスに統合することができます。 はい、もちろん、QGraphicsObjectのプロキシを通じていつでも挿入できますが、はるかに複雑であり、ウィジェットと対話する可能性の一部を削減し、より多くのコードを必要とします。 スクリーンショットは、コンポーネントからの4つの起動例を示しています。 現在のステータスが表示されます。 つまり、すでに多くのことができます。 スクリーンショットには表示されませんが、ツールバーの右ボタンをクリックすると新しいウィンドウが開きます。
QtGuiの代わりにコンポーネントを使用することの長所と短所
長所:
- 豊富なインターフェース作成機能
- 複雑なインターフェイスの実装を簡素化する
- 追加のQDeclarativeViewを作成せずに標準のQML要素を使用する機能
- モバイルデバイスへのアプリケーション転送の簡素化(すべてのコンポーネントに共通のAPIは非常に似ています)
- プラットフォームに依存しません(QtGuiは時々依存します。MacOS Xの起動時に例が表示されます)
短所:
- これはまだ深いアルファであり、多くのマイナーであり、あまり表示されないバグです
- データ層との相互作用の複雑さ(宣言的コンテキスト、プラグイン、その他のメソッドのプロパティ)
- QMLを扱っていない人にとっては珍しい
- おそらくすべてではありません(リリースでもQtGuiのすべての機能がサポートされるとは思いません)
参照資料
- コンポーネントソースリポジトリ
- テストプロジェクト(qmlおよびqtgui)
- Qt Labsのデスクトップコンポーネント: 1、2、3、4