[Qt] Qtを使ってみよう!スクショ作成ソフト実例紹介

はじめに

こちらは、Qt Advent Calendar 2019 19日目の記事です。
この記事では、Qt未経験者にQtの便利さとハードルの低さを伝えることを目的として、Qtについて簡単に紹介し、自作の小さなQtアプリケーション「QCodScreenShot」のソースコードを抜粋して一部紹介します。

Qtについて

Qtとは?

Qtは、C++で書かれたアプリケーションフレームワークで、一つのソースコードで異なるプラットフォームに向けた実行ファイルを生成できるのが大きな特徴です。例えば、Windows、Mac OS、Linuxで動くアプリケーションを、同一のソースコードから作成できます。
主にGUIアプリケーションを容易に作成できるという点で知られていますが、GUI以外の便利な機能も多く提供されています。

Qtの採用事例

株式会社SRAのHPに、Qtの採用事例が紹介されています。
また、hermit4さんによる記事「Qtで作られたアプリケーションを調べてみる」では、Qtを使って開発されているアプリケーションが紹介されています。

Qtのライセンス

Qtを商用利用したい開発者にとってハードルとなるのが、Qtのライセンスです。
Qtは商用有償ライセンスとGPL/LGPLのデュアルライセンスを採用しており、LGPLv3を選択すればソースコードを公開しないプロプライエタリ開発も可能ですが、スタティックリンクをした場合はソースコードまたはオブジェクトファイルを配布しなければならない等制約があります。

詳細は、株式会社SRAが公開しているLGPLライセンスについての注意点をご確認ください。

Qt Creator

IDE「Qt Creator」は、Qtの開発を支援することを目的として提供されているIDEです。ライセンスに則り、無料で利用することが出来ます。
直感的に操作でき、Qtの開発をするうえで便利な機能が多く含まれますので、Qtインストール時に同時にインストールすることをおすすめします。

Qt Creatorには、Qtアプリケーションを編集するための便利なモードがあります。

編集モード

編集モードは、コード編集のためのモードです。
高度な省入力補完機能を持ち、F1キーでカーソル部分のクラスやメソッドについてのヘルプ画面を開くなど、コード編集のための機能が充実しています。

デザインモード

デザインモードでは、パーツを選び、ドラッグ&ドロップすることでGUIを作成することができます。作成したGUIは.uiという拡張子で保存されます。

ヘルプモード

ヘルプモードでは、Qtライブラリの仕様を確認できます。豊富なサンプルがあり、わかりやすく解説されています。
「編集モード」にて前述の通り、編集モードで調べたい対象にカーソルをあわせ、F1キーを押すことでいつでも開くことができるので、わからないことがあるときも検索などで手が止まることがありません。

アプリケーションの紹介

ここでは、自作アプリケーション「QCodScreenShot」について紹介します。QCodScreenShotは、Windowsで動作確認済のデスクトップアプリケーションです。

外観

アイコンを並べたシンプルな外観です。アイコンは、商用利用可能なアイコン配布サイト「ICOOON MONO」さんのものを利用させていただいています。

機能

スクリーンショット撮影

任意の範囲のスクリーンショット撮影が行なえます。

上記のように画面上でドラッグして範囲を指定すると、下記のスクリーンショットが取得できます。

以下のように、任意の場所に矢印を描画することもできます。

タイマー機能

タイマーのアイコンを押すと下記のようにカウントダウンがはじまり、0になるとスクリーンショットを撮影します。

設定機能

さまざまなパラメータを設定できます。

実装解説

ここからは本アプリケーションの実装について一部紹介し、Qtの便利さを紹介していきます。

フレームレス表示

本アプリケーションは、なるべく本来の用途の邪魔にならないよう、タイトルバーやボタンのないUIになっています。

Qtではこのようなウィンドウを簡単に実装することができます。

// mainwindow.cpp
void MainWindow::initialize()
{
  ...
  setWindowFlags(Qt::FramelessWindowHint);
    ...
}

上記処理は、MainWindowクラス生成時に一度だけ実行されるinitializeメソッドの一部です。
QWidgetクラスのsetWindowFlagsメソッドを用いて、Qt::FramelessWindowHintを設定しています。こうすることで、フレームレスなウィンドウを実現できます。

常時最前面表示

アプリケーションのウィンドウを常に最前面表示する処理も、「フレームレス」と同様に実装できます。

// mainwindow.cpp
void MainWindow::initialize()
{
  ...
    if(Settings::value(Settings::StayOnTop)){
    setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);
  }
    ...
}

Qt::FramelessWindowHintフラグに加え、Qt::WindowStaysOnTopHintフラグを設定します。
条件分岐では、「常に最前面表示」の設定が真となっているかどうかを判断しています。

ファイルの上書き確認

保存先ファイルパスとして指定された文字列について、指定されたパスにすでにファイルが存在する際に、上書きしてよいかユーザに確認する処理について紹介します。

bool ScreenShotSaver::checkSaveOk(QString filepath)
{
  if(QFile(filepath).exists() == false){ // 1. 存在確認
    return true;
  }
  if(Settings::value(Settings::OverwriteConfirm) == false){ // 2. 設定確認
    return true;
  }
  QMessageBox::StandardButton button = // 3. 上書きしてよいか質問
      QMessageBox::question(
        nullptr, tr("Confirm"),
        tr("%1 is already exists.\nDo you want to replace it?").arg(filepath));
  return button == QMessageBox::Yes; // 4. 
}
  1. QFile::exists()メソッドにより、ファイルの存在を確認します。存在しない場合、そのまま保存してかまわないため、trueを返します。
  2. 上書き確認をするかどうか確認します。確認しない設定であれば、そのまま上書きしてよいので、trueを返します。
  3. ユーザーに対し、上書き確認を行います。
    QMessageBoxクラスのstaticメソッドであるquestionは、ユーザーに簡単な問いかけをするのに非常に便利です。Yes、Noいずれかのボタンを表示し、ユーザーが押したボタンを戻り値として返します。(Yes、No以外のボタンを表示することもできます)
  4. 戻ってきたボタンがQMessageBox::Yesであればそのまま保存でき、Noであれば保存してはいけないので、そのまま条件式とします。

翻訳のための関数 tr()

「ファイルの上書き確認」のソースにて、文字列がtr()という関数内に存在することにお気づきの方もいるかもしれません。これは、翻訳が必要な文字列であるということをQtの翻訳のしくみに伝えるための特別な関数です。

Qtの多言語対応については、以前[Qt] Qt Linguistの使い方 Qtアプリを国際化してみようという記事で詳細を書きました。よろしければそちらもご覧ください。

スクリーンショットに矢印を追加

このアプリケーションは、作成したスクリーンショットに矢印を描画できます。

ここでは、スクリーンショット画像に矢印の画像を合成する処理を紹介します。

// imageconverter.cpp
QPixmap ImageConverter::addArrow(const QPixmap &image, const QPoint point)
{
  // 元イメージを複製する。
  QPixmap newImage = image.copy();
    // 元イメージ上に描画を行うための`QPainter`オブジェクトを作成。
  QPainter painter(&newImage);
    // 矢印の画像を読みこむ。
  QImage arrowImage;
  arrowImage.load("resource/arrow.png");
    // 指定された点に矢印の先端を描画できるよう、painterの位置をずらす。
  painter.translate(-ARROW_IMAGE_OFFSET);
    // 矢印の画像を描画する。
  painter.drawImage(point, arrowImage);
    // 矢印の画像を描画した画像を返す。
  return newImage;
}

おわりに

コード全体はGitHubにあります

本記事では一部の実装について紹介しましたが、コード全体はGitHubに置いてありますので、Qtでの開発に興味がありましたら是非ご覧ください。

手探りで実装している部分もあるのですぐに答えることをお約束はできませんが、不明な点などあればコメントやTwitterなどでお声がけいただければ適宜当記事に追記したいと思います。

Qtのインストール

Qtのインストールは以下リンクから行えます。
ぜひデスクトップアプリケーションづくりに挑戦してみてください。

関連記事紹介

[Qt] ユーザ定義・独自クラスのデータをQDebugで出力する
https://cod-sushi.com/qt-window-close-delete/
[Qt] Qt Linguistの使い方 Qtアプリを国際化してみよう