ビュースタイルのQt Quickプログラムの作成

Create view-style Qt Quick apps
デフォルトプロジェクトで生成されるQMLはWindowsコンポーネントを使ったデスクトップスタイルのプログラムとなっています。しかしながら、スマートフォンやタブレットのアプリでは基本的にウィンドウの概念がなく、単一のビューで成り立っています。

Qt QuickにはQQuickWindowから派生したQQuickViewが提供されており、このクラスを使うことで、それらの環境に適したアプリを開発することができます。

QQuickViewを使ったひな形の例です。QQuickViewの派生クラス・MainViewを作成し、main()でMainViewの作成と表示を行います。MainViewのコンストラクタでは、リサイズモードに「QQuickView::SizeRootObjectToView(ビューのサイズに応じて最上位QMLコンポーネントサイズを自動で変更)」を指定してから、QMLファイルを呼び出しています。

スマートフォンアプリでは原則としてウィンドウのサイズはOSが決めるので、アプリ側で初期サイズを指定する必要はありませんが、デスクトップOSとのクロスプラットフォーム開発をするのであれば、ビューを表示する前にwidthとheightの値を指定しておきます。
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "mainview.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    // メインビューの作成と表示
    MainView mv;
    mv.show();

    return app.exec();
}
main.qml
import QtQuick 2.9

// Windowの配置や、Itemのサイズ指定は不要
Item {
}
mainview.cpp
#include <QQuickView>

class MainView : public QQuickView
{
    Q_OBJECT
public:
    MainView();
};

MainView::MainView()
{   
    // デスクトップOSならウィンドウサイズを指定
#if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && !defined(Q_OS_WINRT))
    setWidth(640);
    setHeight(480);
#endif

    // 最上位コンポーネントのサイズをビューに合わせる
    this->setResizeMode(QQuickView::SizeRootObjectToView);
    // 最初に適用するQMLをリソースから読み込む
    this->setSource(QUrl("qrc:/main.qml"));
}
せっかくなので、ビュースタイルアプリ特有のイベントを処理してみましょう。ウィンドウのないOSでは、アプリを切り替えるなどでバックグラウンドに移動したときにサスペンドイベントが発生します。Qt 5.2以降では「QGuiApplication::applicationState」にアプリが休止状態であるかどうかが記録されており、applicationStateChangedシグナルを受け取ることで、アプリの休止や復旧時の処理を行うことができます。
appstate.cpp
class MainView : public QQuickView
{
    Q_OBJECT
public slots:
    void onAppStateChanged(Qt::ApplicationState s);
};

MainView::MainView()
{   
    // グローバルなQGuiApplicationオブジェクトはqAppとして呼び出せる
    connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
        this, SLOT(onAppStateChanged(Qt::ApplicationState)));

    // アプリが終了されるときに呼び出される
    connect(qApp, SIGNAL(aboutToQuit()), SLOT(onQuit()));
}

void MainView::onAppStateChanged(Qt::ApplicationState s)
{
    if (s == Qt::ApplicationSuspended){
        // サスペンド状態に入るので、設定データの保存などを行う
    } else if (s == Qt::ApplicationActive){
        // サスペンドから復旧したので、接続の再開などを行う
    }
}

void MainView::onQuit()
{
    // OSによってはアプリ終了時にサスペンドに移行しないため、直接呼び出している
    onAppStateChanged(Qt::ApplicationSuspended);
}
2018/11/06