「Qtの基礎 - プリプロセッサ」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
編集の要約なし
132行目: 132行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
== Q_GADGET ==
==== Q_GADGET ====
<code>QObject</code>クラスを継承せずに、Qtのメタオブジェクトシステムの一部の機能 (プロパティ、列挙型等) を利用可能にするマクロである。<br>
<code>QObject</code>クラスを継承せずに、Qtのメタオブジェクトシステムの一部の機能 (プロパティ、列挙型等) を利用可能にするマクロである。<br>
<br>
<br>
157行目: 157行目:
  Q_DECLARE_METATYPE(Point)
  Q_DECLARE_METATYPE(Point)
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br>
 
==== Q_ENUMマクロ ====
== Q_ENUMマクロ ==
列挙型をQtのメタオブジェクトシステムに登録するために使用する。<br>
列挙型をQtのメタオブジェクトシステムに登録するために使用する。<br>
これにより、列挙型の値を文字列に変換する、または、QMLで使用したりすることが可能になる。<br>
これにより、列挙型の値を文字列に変換する、または、QMLで使用したりすることが可能になる。<br>
<br>
<syntaxhighlight lang="c++">
class TrafficLight : public QObject
{
    Q_OBJECT
private:
    Color m_color = Color::Red;
public:
    enum class Color {
      Red,
      Yellow,
      Green
    };
    Q_ENUM(Color)
    TrafficLight(QObject *parent = nullptr) : QObject(parent) {}
    void setColor(Color color)
    {
      m_color = color;
      qDebug() << "Color set to:" << QMetaEnum::fromType<Color>().valueToKey(static_cast<int>(m_color));
    }
};
</syntaxhighlight>
<br><br>
<br><br>


== Q_DECLARE_METATYPE ==
== 型に関するマクロ ==
==== Q_DECLARE_METATYPE ====
カスタム型を<code>QVariant</code>クラスで使用可能にするためのマクロである。<br>
カスタム型を<code>QVariant</code>クラスで使用可能にするためのマクロである。<br>
これにより、その型を<code>QVariant</code>クラスに格納したり、シグナル / スロットシステムで使用することができる。<br>
これにより、その型を<code>QVariant</code>クラスに格納したり、シグナル / スロットシステムで使用することができる。<br>
<br>
<syntaxhighlight lang="c++">
struct CustomData
{
    int    id;
    QString name;
};
Q_DECLARE_METATYPE(CustomData)
// 使用例
void useCustomData()
{
    CustomData data{1, "Example"};
    QVariant variant = QVariant::fromValue(data);
    if (variant.canConvert<CustomData>()) {
      CustomData retrievedData = variant.value<CustomData>();
      qDebug() << "ID:" << retrievedData.id << "Name:" << retrievedData.name;
    }
}
</syntaxhighlight>
<br><br>
<br><br>



2024年9月4日 (水) 02:24時点における版

概要

Qtにおけるプリプロセッサは、標準的なC++プリプロセッサを拡張して、Qtフレームワークに特化した機能を提供している。
この拡張により、開発者はより効率的にQtアプリケーションを作成できるようになる。
また、クロスプラットフォームアプリケーションの開発がより効率的かつ柔軟になっている。

Qt独自のプリプロセッサの主な特徴として、メタオブジェクトシステムのサポートが挙げられる。
これは、Qtの中核をなす機能であり、シグナル / スロットのメカニズムやプロパティシステムを可能にするものである。

Q_OBJECTマクロは、このメタオブジェクトシステムの中心的な要素である。
このマクロをクラス定義に含めることにより、そのクラスにQtのメタオブジェクト機能が追加される。
これにより、シグナル / スロットの宣言、動的なプロパティの追加、実行時型情報 (RTTI) の拡張等が可能になる。

プリプロセッサは、Q_PROPERTYマクロを使用してクラスのプロパティを宣言する機能も提供している。
これにより、Qtのプロパティシステムを利用でき、GUIデザイナーツールとの連携、QML (Qt Modeling Language) でのプロパティバインディングが容易になる。

また、Qtのプリプロセッサは、プラットフォーム依存のコードを簡単に記述できるようにする機能も備えている。
例えば、Q_OS_*マクロを使用することにより、特定のOS向けのコードを条件付きでコンパイルすることができる。

さらに、国際化 (i18n) のサポートも重要な機能の1つである。
QT_TR_NOOPQ_TRANSLATE_NOOP等のマクロを使用することにより、翻訳可能な文字列を簡単にマークアップすることができる。

これらの機能に加えて、Qtのプリプロセッサは、シグナル / スロットの接続を最適化するためのプライベートシグナル、メモリ管理を支援するためのスマートポインタマクロ等、
様々な便利な機能を提供している。

Qtのプリプロセッサは、moc (Meta-Object Compiler) と呼ばれるツールと密接に連携している。
mocは、Qtのマクロを含むヘッダファイルを解析して、必要なメタオブジェクトコードを生成する。

このプロセスは、一般的に、ビルドシステムにより自動的に処理されるため、開発者は特別な操作を行う必要はない。


QT_VERSION_CHECKマクロ

QT_VERSION_CHECKマクロを使用する場合は、QtGlobalをインクルードする必要がある。
このヘッダファイルには、QT_VERSION_CHECKマクロを含む多くのQtの基本的な定義が含まれている。

 #include <QtGlobal>



クラスに関するマクロ

Q_OBJECT

Qtのメタオブジェクトシステムの中核となるマクロである。
QObjectクラスを継承するサブクラスの定義内で使用され、シグナル / スロットのメカニズム、実行時型情報 (RTTI)、動的プロパティシステムを有効にする。

このマクロを使用することにより、クラスはQtの多くの高度な機能を使用できるようになる。

Q_PROPERTY

クラスのプロパティを宣言するために使用する。

このマクロを使用することにより、C++のメンバ変数をQtのプロパティシステムに統合できる。
これにより、QMLでのプロパティバインディングやGUIデザイナーでのプロパティ編集が可能になる。

また、プロパティの読み取り / 書き込みメソッド、通知シグナル、リセットメソッド等も定義できる。

 class Person : public QObject
 {
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
 
 private:
    QString m_name;
    int m_age = 0;
 
 public:
    Person(QObject *parent = nullptr) : QObject(parent) {}
 
    QString name() const { return m_name; }
 
    void setName(const QString &name)
    {
       if (m_name != name) {
          m_name = name;
          emit nameChanged(m_name);
       }
    }
 
    int age() const { return m_age; }
 
    void setAge(int age)
    {
       if (m_age != age) {
          m_age = age;
          emit ageChanged(m_age);
       }
    }
 
 signals:
    void nameChanged(const QString &name);
    void ageChanged(int age);
 };


Q_INVOKABLE

このマクロをメソッド宣言の前に付加することにより、そのメソッドをQMLから呼び出し可能にする。

一般的に、publicスロットは自動的にQMLから呼び出せるが、publicメソッドはQ_INVOKABLEを使用しない限り呼び出せない。

signals / Q_SIGNAL / Q_SIGNALS

シグナルを宣言するために使用する。

シグナルは、オブジェクト間の通信メカニズムの一部であり、特定のイベントが発生したことを他のオブジェクトに通知するために使用する。

slots / Q_SLOT / Q_SLOTS

スロットを宣言するために使用する。

スロットはシグナルに接続可能な特殊な関数であり、シグナルが発信されたときに呼び出される。

Q_EMIT

シグナルを発信 (emit) する場合に使用するマクロである。 本質的には、C++のソースコード内でシグナルを発信するための構文的な装飾である。

シグナルを発信する場合は、明示的にそれがシグナルの発信であることを示す。 通常は、emitキーワードとして使用するが、Q_EMITはその完全修飾名である。 コンパイル時には何も行わず、コードの可読性を向上させる目的で使用する。

 class MyClass : public QObject
 {
    Q_OBJECT
 
 signals:
    void valueChanged(int newValue);
 
 public:
    void updateValue(int value)
    {
        Q_EMIT valueChanged(value);
        // または、emit valueChanged(value); としてもよい
    }
 };


Q_GADGET

QObjectクラスを継承せずに、Qtのメタオブジェクトシステムの一部の機能 (プロパティ、列挙型等) を利用可能にするマクロである。

軽量なオブジェクトを作成する場合に有効である。

 class Point
 {
    Q_GADGET
    Q_PROPERTY(int x MEMBER m_x)
    Q_PROPERTY(int y MEMBER m_y)
 
 private:
    int m_x,
        m_y;
 
 public:
    Point(int x = 0, int y = 0) : m_x(x), m_y(y) {}

    int x() const { return m_x; }
    int y() const { return m_y; }
 };
 
 Q_DECLARE_METATYPE(Point)


Q_ENUMマクロ

列挙型をQtのメタオブジェクトシステムに登録するために使用する。
これにより、列挙型の値を文字列に変換する、または、QMLで使用したりすることが可能になる。

 class TrafficLight : public QObject
 {
    Q_OBJECT
 
 private:
    Color m_color = Color::Red;
 
 public:
    enum class Color {
       Red,
       Yellow,
       Green
    };
 
    Q_ENUM(Color)
 
    TrafficLight(QObject *parent = nullptr) : QObject(parent) {}
 
    void setColor(Color color)
    {
       m_color = color;
       qDebug() << "Color set to:" << QMetaEnum::fromType<Color>().valueToKey(static_cast<int>(m_color));
    }
 };



型に関するマクロ

Q_DECLARE_METATYPE

カスタム型をQVariantクラスで使用可能にするためのマクロである。
これにより、その型をQVariantクラスに格納したり、シグナル / スロットシステムで使用することができる。

 struct CustomData
 {
    int     id;
    QString name;
 };
 
 Q_DECLARE_METATYPE(CustomData)
 
 // 使用例
 void useCustomData()
 {
    CustomData data{1, "Example"};
    QVariant variant = QVariant::fromValue(data);
 
    if (variant.canConvert<CustomData>()) {
       CustomData retrievedData = variant.value<CustomData>();
       qDebug() << "ID:" << retrievedData.id << "Name:" << retrievedData.name;
    }
 }



翻訳に関するマクロ

QT_TR_NOOP

国際化 (i18n) のために使用する。

このマクロで囲まれた文字列は、翻訳ツールによって抽出可能になるが、実行時には通常の文字列として扱われる。

Q_TRANSLATE_NOOP

国際化 (i18n) のために使用するマクロである。
翻訳が必要な文字列を標識付けするために使用するが、その場では翻訳を行わない。

文字列を翻訳ツールで認識可能にするが、実行時には元の文字列をそのまま返す。
後で翻訳が必要になる可能性のある文字列を準備する場合に使用する。

一般的に、QObject::trメソッドやQCoreApplication::translateメソッドと組み合わせて使用する。

以下の例では、"File not found"という文字列が翻訳ツールにより抽出可能になるが、変数messageには元の英語の文字列がそのまま格納されている。
後で必要に応じて、QCoreApplication::translateメソッドを使用して実際の翻訳を行う。

 const char *message = Q_TRANSLATE_NOOP("MyDialog", "File not found");
 
 // 後で翻訳する場合
 QString translatedMessage = QCoreApplication::translate("MyDialog", message);



Q_ARGマクロ

Q_ARGマクロは、Qtフレームワークで提供されているマクロの1つであり、主にQMetaObject::invokeMethodメソッドと組み合わせて使用される。
このマクロの主な目的は、メタオブジェクトシステムを介してメソッドを呼び出す時に、引数の型と値を指定することである。

Q_ARGマクロのシンタックスを以下に示す。

 // <引数の型>は、C++の型 (int型, QStringクラス, QVariantクラス等)
 // <値>は、その型の具体的な値である
 
 Q_ARG(<引数の型>, <>)


Q_ARGマクロは、スレッド間通信やイベントループを介したメソッド呼び出し等、直接的なメソッド呼び出しが難しい場合に特に有効である。
例えば、あるスレッドから別のスレッドにあるオブジェクトのメソッドを呼び出す場合等に使用される。

以下の例では、someObjectオブジェクトのupdateValueメソッド (int型とQStringクラスの2つの引数を持つ) を呼び出している。
Q_ARGマクロを使用して、このメソッドの引数の型と値を指定している。

 QMetaObject::invokeMethod(someObject, "updateValue", 
                           Qt::QueuedConnection,
                           Q_ARG(int, 42),
                           Q_ARG(QString, "Hello"));


Q_ARGマクロのメリットを以下に示す。

  • 型安全性
    コンパイル時に引数の型チェックが行われるため、誤った型の引数を渡すことによるランタイムエラーを防ぐことができる。
  • 可変個数の引数を持つメソッドの呼び出しに対応
    必要な数だけQ_ARGマクロを追加することにより、任意の数の引数を持つメソッドを呼び出すことができる。


ただし、Q_ARGマクロは、ポインタ型や参照型の引数を直接扱うことはできない。
ポインタ型や参照型の引数を使用する場合は、QVariantクラスを介して渡す必要がある。

Q_ARGマクロは、Qtのシグナル / スロットシステムと密接に関連しており、Qtプログラミングにおいて柔軟なメソッド呼び出しを実現するための重要なツールの1つである。