Qt + QMLと簡単な例

Qtは、クロスプラットフォームソフトウェアを作成するための便利で柔軟なツールです。 付属のQMLにより、ユーザーインターフェイスを作成するときに完全なアクションの自由が提供されます。
QtとQMLの組み合わせを使用することの便利さは複数回言及されているため、長所と短所についてはこれ以上説明しませんが、簡単なQtアプリケーションの例を段階的に説明します。

これは最小限のアプリケーションであり、その意味は単純です-キーボードの任意のキーを押すと、画面にランダムな画像が表示され、再びランダムな効果音が再生されます。

ユーザーインターフェイスは、Qtのソフトウェア部分であるQMLで完全に実装されます。

Qtをまだインストールしていない場合は、 qt.nokia.com / downloadsダウンロードページにアクセスし、「 Qt SDK:開発環境の完成 」セクションでプラットフォームのバイナリをダウンロードします。 そして、実際にはインストールします。

Qt Creatorを実行し、メニュー項目[ファイル ]-> [ 新しいファイルまたはプロジェクト ]を選択します。 開いたウィンドウで、 Qt Project C ++ -> Gui Qt application 、そしてSelectボタンをクリックします。

Qt

新しいウィンドウで、プロジェクトの名前を入力し、プロジェクトへのパスを指定して、 「次へ 」をクリックします。

次のウィンドウで、フォームの作成のチェックを外します 。 最後の1 つでは 、[ 完了 ]ボタンをクリックするだけです。 これで、アプリケーションのフレームワークが作成されました。

Qt

まず、プロジェクトファイル( 4Toddler.pro )の行にqt-declarativeモジュールをプロジェクトに追加します。

QT += core gui

宣言を追加する
QT += core gui declarative

次に、メインウィンドウの基本クラスを変更し、 QMainWindowQDeclarativeViewに置き換え、 QDeclarativeViewヘッダーファイルを含めます
#include <QDeclarativeView>

class MainWindow : public QDeclarativeView
{
...
}


コンストラクターの実装から、基本クラスQMainWindow(親)の初期化を不要にしました。

ここでプロジェクトを組み立てて起動すると、空のウィンドウが表示されます。 だから、あるべきです、なぜなら Qmlインターフェイスはまだ作成または初期化されていません。

新しいQMLファイルをプロジェクトに追加します。これを行うには、プロジェクトを右クリックします

画像

新しい...を追加し、 Qtセクション、 Qt QMLファイルテンプレートを選択しますmainという名前を付けてから、 NextFinishを付けます。

画像

ウィザードは、1つのRectangle要素を含むファイルを作成しました。これがユーザーインターフェイスのメイン要素になります。 いくつかの新しいプロパティを追加し、それらの値を設定します。

Rectangle
{
// ,
//
id: canvas;

// ,
color: "black"

//
//
anchors.fill: parent

//
focus: true
}


これまでのところ、特別なものは何もありません。ただの黒い背景です。 QMLファイルのダウンロードコードを追加して、何が起こったかを確認します。 これを行うには、新しいメソッドをウィンドウに追加します
void MainWindow::Init()
{
// , QML
QString contentPath;

#ifdef QT_DEBUG
//
contentPath = "D:/MyProjects/QT/4Toddler" ;
#else
// ,
contentPath = QApplication::applicationDirPath();
#endif

setFocusPolicy(Qt::StrongFocus);
// QML
// ,
// QDeclarativeView::SizeViewToRootObject
setResizeMode(QDeclarativeView::SizeRootObjectToView);

// QML
setSource(QUrl::fromLocalFile(contentPath + "/main.qml" ));
}

次に、 main.cppファイルの行を置き換えます
int main( int argc, char *argv[])
{
...
w.show();
...
}


int main( int argc, char *argv[])
{
...
w.showFullScreen();
...
}

ウィンドウは全画面に拡大します。 アプリケーションを開始する前に、ウィンドウを閉じるためのボタンを追加しましょう。 今後、同じコードを何度も記述せずに新しいQMLファイルをプロジェクトに追加し、それをWindowButtonと呼ぶために、ウィンドウに2つのボタンがあると言います。

WindowButton要素を再利用して、各インスタンスの特定のプロパティのみを変更します。 ボタンはアイコンの形で作成されます。それぞれのアイコンファイルへのパスを設定し、マウスの左ボタンをクリックするためのハンドラーを変更します。 以下はコメント付きの完成品コードです
Image
{
//
id: button

// , ""
MouseArea
{
//
// Image
anchors.fill: parent

id: mouseArea

// callback
onClicked: callback()
}
}

ウィンドウにいくつかのボタンを追加します
//
//
Row
{
//
//
anchors.right: parent.right;
// , 4
anchors.rightMargin: 4;
//
//
anchors.top: parent.top;
// , 4
anchors.topMargin: 4;

//
spacing: 4

WindowButton
{
// " "
id: about;

//
// ,
// QML
source: "about.png" ;

// ,
//
// onClicked: callback()
function callback()
{
}
}

WindowButton
{
//
id: exit;

source: "exit.png" ;

function callback()
{
}
}
}


動作させるために、ボタンごとに両方のコールバックメソッドを実装する必要があります。 ウィンドウを閉じるには、ウィンドウクラスに実装するQuitメソッドを呼び出します。 これを行うには、クラスを宣言に追加します
Q_INVOKABLE void Quit();

次に、このメソッドを実装します
void MainWindow::Quit()
{
QApplication::quit();
}

このメソッドをQMLから見えるようにすることは残っています。 Initメソッドで、1行の行を追加します。これにより、ウィンドウのインスタンスがQMLで表示されます
rootContext()->setContextProperty( "window" , this );

名前でこのオブジェクトにアクセスできます-window 、名前は任意です。 ウィンドウを閉じるボタンの実装を追加します
function callback()
{
window.Quit();
}

Q_INVOKABLEとして宣言されているメソッドのみを呼び出すことできることに注意してください。 Initメソッドから、メインウィンドウを呼び出すことはできません。

完了、開始、黒い画面が表示されます。 終了ボタンをクリックしてウィンドウを閉じるだけです。 彼らはクリックし、ホバーしてもボタンを押してもボタンの状態は変わらないことがわかります。これは「無生物」のように見えます。 状態を追加して復活させます:
Image
{
...
states:[
State
{
//
name: "hovered" ;
// ,
//
when: mouseArea.pressed;
//
//
PropertyChanges { target: button; opacity: 1;}
},
State
{
name: "normal"
//
//
when: mouseArea.pressed == false ;
PropertyChanges { target: button; opacity: 0.7; }
}
]
}

要素は、 whenで指定され条件が満たされたときに自動的に、またはstateプロパティを変更して手動で特定の状態になります。

立ち上げられ、押されて、透明度が変化している、それは良いが、十分な滑らかさではない。 次のコードを追加します。
Image
{
...
Behavior on opacity
{
// 100
// 100
// 0,1
NumberAnimation { duration: 100 }
}
}

動作はアニメーションを作成するのに非常に便利な要素であり、指定したプロパティの変更方法(この場合はボタンの透明度)を指定できます。

半透明から不透明な状態へのスムーズな移行を、まったく異なる問題から始めます。


プログラムウィンドウは完全にQMLで実装されます。 これは、をクリックすると表示されるモーダルウィンドウになります。 ウィンドウの任意の場所でマウスの左ボタンをクリックすると、ボタンが消えます。 新しいQMLファイルAbout.qmlをプロジェクトに追加します。



このウィンドウのすべてのコードをすぐに説明します
//
Rectangle
{
id: about

//
//
function show()
{
about.opacity = 1;
}

//
function hide()
{
about.opacity = 0;
}

//
color: "transparent"
//
opacity: 0

//
//
// id: canvas
width: parent.width
height: parent.height

//
// opacity > 0
visible: opacity > 0

// ,
Rectangle
{
anchors.fill: parent

opacity: 0.5

color: "gray"
}

//
// " ..."
Rectangle
{
id: dialog

//
width: 360
height: 230

//
//
// ,
x: parent.width / 2 - dialog.width / 2;
y: parent.height / 2 - dialog.height / 2;
// z ,
// z ,
//
z: 10

border.color: "gray"

Text
{
text: "4 Toddler"

font.bold: true

font.pixelSize: 22

//
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}

Behavior on opacity
{
NumberAnimation { duration: 100 }
}

MouseArea
{
//
anchors.fill: parent;

//
onClicked: hide();
}
}

まず、プロパティに注意を引きたいと思います
width: parent.width

これは単なる幅の割り当てではなく、表示中に親要素の幅が変更されると、子の幅が再計算されます。 あなたについては知りませんが、この機能はQMLを「ピッキング」する過程で私を喜ばせました。 次の行も興味深いものです。

visible: opacity > 0

プロパティは設定できるだけでなく、計算もできます。

をクリックすると、ダイアログとコードを追加して表示します。 キャンバス要素の最後に、 Main.qmlファイルにコードを追加します

Rectangle
{
id: canvas
..
About
{
id: aboutDlg
}
}

ウィンドウを表示するには、次の行を追加します

aboutDlg.show();

ボタンのコールバック関数に

WindowButton
{
id: about;
...
function callback()
{
aboutDlg.show();
}
}

次に、実際に主な機能を追加します。 任意のキーを押したときにランダムな画像を表示することから始めましょう。 画像はImage要素になります。この要素は別のファイルで定義します。 Block.qmlファイルをプロジェクトに追加します
Image
{
id: block;

// ,
//
property bool remove: false
//
property bool show: false

opacity: 0;
fillMode: Image.Stretch;

states: [
State
{
// ,
// ,
name: "remove" ; when: remove == true ;
PropertyChanges { target: block; opacity: 0 }
StateChangeScript { script: block.destroy(1000); }
},
State
{
// ,
// ,
name: "show" ; when: show == true ;
PropertyChanges { target: block; opacity: 1 }
}
]

Behavior on opacity { NumberAnimation { duration: 300 } }
}

キーボードのいずれかのキーを押すと、任意の画像を含むブロックが表示されます。 新しいmain.jsファイルをプロジェクトに追加します。 その中で、キーボードのキーストロークハンドラを定義します。
//
var component = Qt.createComponent( "block.qml" );

//
var maxBlocksCount = 10;

// ,
var blocksArray = new Array();

//
function handleKey()
{
// x - 0
var x = Math .floor( Math .random() * canvas.width);
// y - 0
var y = Math .floor( Math .random() * canvas.height);

// ,
//
createNewBlock(x, y);
}

//
function createNewBlock(x, y)
{
if (component.status != Component.Ready)
{
return false ;
}

//
if (blocksArray.length > maxBlocksCount)
{
removeAllBlocks();
}

var newBlock = component.createObject(canvas);

if (newBlock == null )
{
return false ;
}

//
// randomIcon
var iconFile = window.randomIcon;

newBlock.source = ( "Icons/" + iconFile);

newBlock.x = x;
newBlock.y = y;

// show
newBlock.show = true ;

blocksArray.push(newBlock);

//
window.PlaySound();

return true ;
}

//
function removeAllBlocks()
{
for ( var i = 0; i < blocksArray.length; ++i)
{
blocksArray[i].remove = true ;
}

while (blocksArray.length != 0)
{
blocksArray.pop();
}
}

コードからわかるように、 randomIconプロパティとメインウィンドウのPlaySound関数を実装する必要 があります。

MainWindowクラスの宣言にプロパティを追加します

Q_PROPERTY(QString randomIcon READ RandomIcon)

そして関数宣言

QString RandomIcon();

次に実装:

QString MainWindow::RandomIcon()
{
QStringList iconFilesList;
QString searchPath = m_ContentPath + "/Icons/" ;

QDir directory = QDir(searchPath);
QStringList filters;
filters << "*.png" ;
directory.setNameFilters(filters);
// png
iconFilesList = directory.entryList(QDir::AllEntries);

//
int fileIdx = qrand() % iconFilesList.count();

//
return iconFilesList.at(fileIdx);
}

サウンドファイルに関数を追加して、効果音を再生します
Q_INVOKABLE void PlaySound();

および実装
void MainWindow::PlaySound()
{
QStringList soundFilesList;
QDir directory = QDir(m_ContentPath + "/Sounds/" );
QStringList filters;
filters << "*.wav" ;
directory.setNameFilters(filters);

// wav
soundFilesList = directory.entryList(QDir::AllEntries);
//
int fileIdx = qrand() % soundFilesList.count();

//
QString soundFile = m_ContentPath + "/Sounds/" + soundFilesList.at(fileIdx);
//
QSound::play(soundFile);
}

残っているほとんどすべては、キーストロークハンドラーをルート要素に追加し、関数を呼び出して新しい要素を作成することです。 main.qmlファイルで、スクリプトをmain.qmlファイルに表示します

import Qt 4.7
import "main.js" as Main


キャンバス要素内のハンドラー自体

Rectangle
{
id: canvas
...
Keys.onPressed: { if ( event .isAutoRepeat == false ) { Main.handleKey(); } }

それだけです-私たちは走って楽しむことができます。



私が約束したように、プログラムはシンプルですが、私の意見では、これはQMLを学び始めたばかりの人にとってはかなり興味深い「ゲーム」プラットフォームです。 完璧に制限はありません。誰かがそれをもっと価値のあるものに発展させるかもしれません。

プロジェクトのアーカイブはここからダウンロードできます

Source: https://habr.com/ru/post/J110544/


All Articles