このページでは

カスタム Qt 型の作成

概要

Qt を使用してユーザーインターフェースを作成する際、特に特殊なコントロールや機能を備えたインターフェースを作成する場合、開発者は、Qt の既存の値型と併用したり、それらに代わるものとして使用できる新しいデータ型を作成する必要があることがあります。

QSize 、QColor 、QString などの標準型は、すべてQVariant オブジェクトに格納したり、QObject ベースのクラスでプロパティの型として使用したり、シグナル・スロット通信で送信したりすることができます。

このドキュメントでは、カスタム型を取り上げ、標準の Qt 型と同様に格納できるよう、それを Qt のオブジェクトモデルに統合する方法について説明します。その後、シグナルとスロットの接続でそのカスタム型が使用できるよう、登録する方法について示します。

カスタム型の作成

始める前に、作成するカスタム型が `QMetaType` で規定されているすべての要件を満たしていることを確認する必要があります。つまり、以下の要素を提供している必要があります:

  • パブリックのデフォルトコンストラクタ、
  • パブリックのコピーコンストラクタ、および
  • パブリックなデストラクタ。

以下のMessage クラスの定義には、これらのメンバが含まれています:

class Message
{
public:
    Message() = default;
    ~Message() = default;
    Message(const Message &) = default;
    Message &operator=(const Message &) = default;

    Message(const QString &body, const QStringList &headers);

    QStringView body() const;
    QStringList headers() const;

private:
    QString m_body;
    QStringList m_headers;
};

また、このクラスは通常の使用のためのコンストラクタと、プライベートデータを取得するために使用される2つのパブリックメンバー関数も提供しています。

QMetaType による型の宣言

Message クラスは、使用可能にするために適切な実装さえあれば十分です。しかし、Qtの型システムは、何らかの補助なしでは、このクラスのインスタンスをどのように格納、取得、シリアル化すればよいかを理解できません。例えば、Message の値をQVariant に格納することはできません。

Qtにおいてカスタム型を扱うのはQMetaType クラスです。このクラスに型を認識させるには、そのクラスが定義されているヘッダーファイル内で、Q_DECLARE_METATYPE()マクロを呼び出します:

Q_DECLARE_METATYPE(Message);

これにより、Message の値をQVariant オブジェクトに格納し、後で取得することが可能になります:

QVariant stored;
stored.setValue(message);
    ...
Message retrieved=qvariant_cast<Message>(stored);
qDebug() << "Retrieved:" << retrieved;
retrieved=qvariant_cast<Message>(stored);
qDebug() << "Retrieved:" << retrieved;

Q_DECLARE_METATYPE() マクロを使用すると、これらの値をシグナルの引数として使用することも可能になりますが、これは直接的なシグナル・スロットの接続の場合に限られます。このカスタム型をシグナル・スロット機構で一般的に使用できるようにするには、いくつかの追加作業を行う必要があります。

カスタムオブジェクトの作成と破棄

前のセクションでの宣言により、この型は直接的なシグナル・スロット接続で使用可能になりますが、異なるスレッド間のオブジェクト間で確立されるような、キュー化されたシグナル・スロット接続では使用できません。これは、メタオブジェクトシステムが、実行時にカスタム型のオブジェクトの作成と破棄をどのように処理すべきかを知らないためです。

実行時にオブジェクトを作成できるようにするには、qRegisterMetaType() テンプレート関数を呼び出して、その型をメタオブジェクトシステムに登録します。これにより、その型を使用する最初の接続を確立する前にこの関数を呼び出せば、キュー付きシグナル・スロット通信でもその型が利用可能になります。

「Queued Custom Type」の例では、Block クラスが宣言されており、これはmain.cpp ファイルに登録されています:

intmain(intargc, char *argv[])
{
    QApplication app(argc,argv);
    ...
    qRegisterMetaType<Block>();
    ...
    returnapp.exec();
}

この型は、後でwindow.cpp ファイル内のシグナル・スロット接続で使用されます:

Window::Window(QWidget *parent)
    : QWidget(parent), thread(new RenderThread(this))
{
    ...
    connect(thread, &RenderThread::sendBlock,
            this, &Window::addBlock);
    ...
    setWindowTitle(tr("Queued Custom Type"));
}

登録されていない型がキュー接続で使用された場合、コンソールに警告が表示されます。例えば:

QObject::connect: Cannot queue arguments of type 'Block'
(Make sure 'Block' is registered using qRegisterMetaType().)

型の表示可能化

デバッグの目的で、カスタム型をprintableにすることは非常に役立つことがよくあります。次のコードのように:

Message message(body,headers);
qDebug() << "Original:" << message;

これは、その型用のストリーミング演算子を作成することで実現されます。この演算子は、多くの場合、その型のヘッダーファイル内で定義されています:

QDebug operator<<(QDebug dbg, const Message &message);

ここでは、Message 型の実装において、出力形式をできるだけ読みやすいものにするために、ある程度の工夫が凝らされています:

QDebug operator<<(QDebug dbg, const Message &message)
{
    QDebugStateSaver saver(dbg);
    const QList<QStringView> pieces = message.body().split(u"\r\n", Qt::SkipEmptyParts);
    if (pieces.isEmpty())
        dbg.nospace() << "Message()";
    else if (pieces.size() == 1)
        dbg.nospace() << "Message(" << pieces.first() << ")";
    else
        dbg.nospace() << "Message(" << pieces.first() << " ...)";
    return dbg;
}

デバッグストリームに送信される出力は、もちろん、好みに応じてシンプルにも複雑にもすることができます。なお、この関数が返す値はQDebug オブジェクトそのものですが、読みやすさを高めるためにストリームをスペース文字で埋めるQDebug のmaybeSpace()メンバ関数を呼び出すことで、この値が得られることがよくあります。

参考資料

Q_DECLARE_METATYPE() マクロおよびqRegisterMetaType() 関数のドキュメントには、それらの使用方法や制限事項に関するより詳細な情報が記載されています。

「キュー化されたカスタム型」の例では、このドキュメントで説明した機能を用いてカスタム型を実装する方法を示しています。

「デバッグ手法」ドキュメントには、前述のデバッグメカニズムの概要が記載されています。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.