Qtウィジェットアプリ開発メモ

勝手の分からないことだらけなので、つれづれにメモ。

開発環境のインストール

  • オープンソース版Qt の Qt Creator を使用
  • インストール時の「コンポーネントの選択」がやや分かりにくいが、「Qt」の中のバージョンを一つ選び (とりあえずベータ版でない最新を選ぶ)、Windowsのデスクトップアプリ開発であれば「MSVC 2019 64-bit」と「Qt Debug Information Files」をチェックする。

  • 「Qt Debug Information Files」をインストールしないと、デバッグ実行しようとすると下記のようなメッセージが出て、実行中のソースを追えない。


ビルドツール (CMake vs QMake)

  • ビルドツールには CMake と QMake があり、プロジェクト作成時に選べる
  • QMakeはQtで従来から使われていたビルドツール。CMakeは汎用のビルドツール。
  • QMakeのほうが分かりやすい。CMakeは構文が難解だが汎用性がある。
    (特にサードパーティーのライブラリ利用はCMakeが有利)
  • Qt 6ではCMakeがデフォルトになっている。
  • 後々のことを考え、CMakeを使うことにする。

メインウィンドウ (MainWindow)

  • タイトルの設定:プロパティ windowTitle
  • サイズ固定にする:プロパティ minimumSize と maximumSize を同じ値に設定

メインウィンドウのマウスイベント

class MainWindow : public QMainWindow
{
    ...
protected:
    void mousePressEvent(QMouseEvent *event) override {
        QPoint mousePos = event->pos();
        qDebug() << "X:" << mousePos.x() << " Y:" << mousePos.y();
    }
    void mouseMoveEvent(QMouseEvent *event) override{
        if (event->buttons() & Qt::LeftButton){
            ...
        }
    }
    void mouseReleaseEvent(QMouseEvent *event) override{
        ...
    }
}

メインウィンドウの描画イベントと描画要求

    void paintEvent(QPaintEvent *event) override{
        ...
    }
    update();

デバッグログ出力

#include <QtCore/QDebug>

void func(int x) {
    qDebug() << "x = " << x
}

処理時間計測

#include <QElapsedTimer>
#include <QtCore/QDebug>

void func() {
    QElapsedTimer timer;
    timer.start();
    ...(処理)...
    qint64 elapsedTime = timer.elapsed();
    qDebug() << "time: " << elapsedTime << "msec";
}

高DPIモニタでの問題

ノートPCなどの高DPIモニタでは表示に不具合が生じる場合がある。Qt6のバグだろうか? 暫定的な対策として main関数の最初に下記を追加する。ただしこれによりスケーリングが無効化される。

int main(int argc, char *argv[])
{
#ifdef Q_OS_WINDOWS
    qputenv("QT_ENABLE_HIGHDPI_SCALING", "0");
#endif

リソースファイル

  • リソースファイルを実行ファイルのディレクトリにコピーされるようにしたい。
  • プロジェクトエクスプローラで、プロジェクトの右クリックメニューから既存ファイル/ディレクトリの追加はできるが、それだけではファイルはコピーされない。
  • 以下では、リソースファイルは resource ディレクトリにまとめるものとする。
  • CMakeList.txt に add_custom_command でファイルコピーのコマンドを追加する。
set(RES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/resource)
set(TGT_PSTH ${CMAKE_BINARY_DIR})
add_custom_command(
    TARGET プロジェクト名 POST_BUILD
    COMMAND cp -rf ${RES_PATH} ${TGT_PSTH}
)
  • ただし、Windowsの場合はコピーのコマンドが違うし、ファイルパスの区切り文字がスラッシュではなくバックスラッシュであるため、細工が必要
set(RES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/resource)
set(TGT_PSTH ${CMAKE_BINARY_DIR})
if(WIN32)
    string(REPLACE "/" "\\" RES_PATH ${RES_PATH})
    string(REPLACE "/" "\\" TGT_PSTH ${TGT_PSTH}/resource)
    set(COPY_CMD xcopy /I /S /Y)
else()
    set(COPY_CMD cp -rf)
endif()

add_custom_command(
    TARGET プロジェクト名 POST_BUILD
    COMMAND ${COPY_CMD} ${RES_PATH} ${TGT_PSTH}
)

Windows用のデプロイ

  • 実行ファイル単体では動作できない。
  • リソースファイルや必要なDLLなどを集めて一つのフォルダに配置する操作が必要。
  • 環境変数 PATH に、windeployqt.exe のパスを追加する。(筆者の環境では C:\Qt\6.6.2\msvc2019_64\bin )
  • 下記のバッチ処理を deploy.bat という名前のファイルでソースフォルダに配置
    この例では実行ファイルの他にリソースファイルとして *.bmp もコピーする。
if not exist deploy\ (
mkdir deploy
)
xcopy /C /Y *.exe deploy\
xcopy /C /Y *.bmp deploy\
windeployqt --dir deploy %1.exe
  • 「プロジェクト」→「ビルド設定」の「ビルド設定を編集」で「Release」を選択

  • 「ビルドステップを追加」で「独自プロセスステップ」を追加し下記を設定
    • コマンド: %{sourceDir}\deploy.bat
    • 引数: 実行ファイル名 (拡張子なし)
    • 作業ディレクトリ: %{buildDir}

  • 以上の設定で、「Release」ビルド時にはビルド先フォルダの下の deploy フォルダに実行ファイルおよびリソースファイル、DLLなどがコピーされる。