Posted at
QtDay 15

QVariantを便利に使おう

More than 1 year has passed since last update.

この記事は Qt Advent Calendar 2016 15日目の記事です。

QVariantはQtにおけるバリアント型のクラスです。

QString, QPointのようなQtの型から、int, double のようなプリミティブ型まで

多くの型を格納することができます。

また、void*, QObject*, QWidget*というポインタ型も扱えます。

そのため、多くの型に対応する必要がある場合などに役立ちます。

このクラスはQSettingsなどで活用する機会があるのですが、

直接扱う記事はQiitaになかったので書いてみました。


基本的な使い方

QVariantに値を格納するには以下のメソッドを使います。


  • コンストラクタ

  • QVariant::setValue(const T &)

  • QVariant::fromValue(const T &) [static]

void set_value()

{
QString text("text");
QVariant variant1(text); // constructor
QVariant variant2;
variant2.setValue(text); // QVariant::setValue()
QVariant variant3 = QVariant::fromValue(text); // QVariant::fromValue() [static]
}

反対にQVariantから値を取り出すには以下のメソッドを使います。


  • toメソッド

  • QVariant::value()

void get_value()

{
QVariant variant(QString("text"));
QString text1 = variant.toString(); // to method
QString text2 = variant.value<QString>(); // QVariant::value<T>()
}


具体的な使い方

QSettings を使う例がわかりやすいかと考えたのですが、

昨年のアドベントカレンダーに@taura_noさんのQSettingsでアプリケーションの設定を保存するという記事がありましたので、

他の一例としてQVariantMapを用いた方法を示します。

void getFileName(QVariantMap & map)

{
QString caption = map["caption"].toString();
QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, caption);
map["fileName"] = QVariant::fromValue(fileName);
}

void func()
{
QVariantMap map;
QString caption("Let's select file!");
map["caption"] = QVariant::fromValue(caption);
getFileName(map);
qDebug() << map["fileName"].toString();
}

上記のgetFileNameメソッドはファイル名を取得するメソッドですが、

引数にQVariantMapを渡すことで引数の変更に柔軟な対応ができるようにしています。

後にファイル名の取得方法が変更になった場合

必要に応じて呼び出し元と呼び出し先でQVariantMapのkey/valueを修正しますが、

getFileNameメソッドの引数は一切変更の必要が生じません。

尤も、保守の観点からは引数が明らかである方が望ましいです。

このような方法は自衛的なプログラミング方法として使うべきで、

引数の変更が容易にできないが、仕様の変更が考えられるなどの

限られたケースにおいて最小限で利用がよいでしょう。