Qtプログラミング必見!QSettings::childKeys()を使った設定探索の具体例

2025-05-27

QSettings::childKeys() とは

QSettings クラスは、アプリケーションの永続的な設定を保存および取得するためのQtのクラスです。ユーザー設定やアプリケーションの状態などを、プラットフォームに応じた永続的なストレージ(Windowsではレジストリ、macOSではplistファイル、Unix系システムではINIファイルなど)に保存できます。

QSettings::childKeys() メソッドは、現在の設定グループ直下にあるすべてのキー(設定項目名)のリストを返します。

もう少し詳しく説明すると、QSettingsは設定を階層的に管理できます。例えば、以下のような設定があるとします。

[General]
  UserName = "John Doe"
  Locale = "en_US"
[Database]
  Host = "localhost"
  Port = 5432
  User = "admin"

この場合、

  • 現在のグループが Database の場合(settings.beginGroup("Database"); の後)

    • childKeys() を呼び出すと、"Host""Port""User" というキー名のリストが返されます。
  • 現在のグループが General の場合(settings.beginGroup("General"); の後)

    • childKeys() を呼び出すと、"UserName""Locale" というキー名のリストが返されます。
    • このグループ内にはさらに子グループがないため、childGroups() は空のリストを返します。
    • childKeys() を呼び出すと、空の文字列リストが返されます。これは、ルートグループの直下にはキーがなく、グループ(GeneralDatabase)しかないためです。
    • 代わりに、childGroups() を呼び出すと、"General""Database" というグループ名のリストが返されます。
#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    QSettings settings;

    // 設定を書き込む
    settings.setValue("General/UserName", "John Doe");
    settings.setValue("General/Locale", "en_US");
    settings.setValue("Database/Host", "localhost");
    settings.setValue("Database/Port", 5432);

    qDebug() << "--- ルートグループのchildKeys() ---";
    QStringList rootKeys = settings.childKeys();
    if (rootKeys.isEmpty()) {
        qDebug() << "ルートグループにはキーがありません。";
    } else {
        foreach (const QString &key, rootKeys) {
            qDebug() << "Key: " << key;
        }
    }

    qDebug() << "--- GeneralグループのchildKeys() ---";
    settings.beginGroup("General");
    QStringList generalKeys = settings.childKeys();
    foreach (const QString &key, generalKeys) {
        qDebug() << "Key: " << key;
    }
    settings.endGroup(); // beginGroupとendGroupはセットで使用する

    qDebug() << "--- DatabaseグループのchildKeys() ---";
    settings.beginGroup("Database");
    QStringList databaseKeys = settings.childKeys();
    foreach (const QString &key, databaseKeys) {
        qDebug() << "Key: " << key;
    }
    settings.endGroup();

    return 0;
}

このコードを実行すると、以下のような出力が得られます。

--- ルートグループのchildKeys() ---
ルートグループにはキーがありません。
--- GeneralグループのchildKeys() ---
Key:  "UserName"
Key:  "Locale"
--- DatabaseグループのchildKeys() ---
Key:  "Host"
Key:  "Port"


QSettings::childKeys() のよくあるエラーとトラブルシューティング

QSettings::childKeys() は非常に便利なメソッドですが、誤解や設定の不備によって期待通りの結果が得られないことがあります。以下に主なエラーとその解決策を挙げます。

想定したキーが返されない(リストが空、または一部のキーが足りない)

これは最もよくある問題です。原因はいくつか考えられます。

a. QSettings オブジェクトが正しい設定ファイル/場所を指していない

  • トラブルシューティング
    • QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName() を、QSettings オブジェクトを生成する前に設定しているか確認します。
    • QSettings のコンストラクタで、読み込みたい設定に対応する組織名とアプリケーション名を正確に指定しているか確認します。
    • 特定のファイル(例: INIファイル)を直接指定して読み込む場合は、QSettings settings("path/to/your/file.ini", QSettings::IniFormat); のように、正しいパスとフォーマットを指定しているか確認します。パスが相対パスの場合、実行時のカレントディレクトリが異なる可能性もあります。絶対パスで試してみるか、QDir::currentPath() などで確認してください。
    • 重要
      Windowsのレジストリなど、プラットフォーム固有の場所は、アプリケーションが32bit/64bitどちらでコンパイルされたかによって異なる場合があります(例: HKEY_LOCAL_MACHINE\SOFTWAREHKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node)。特にシステム設定を読み込む場合は、QSettings::Registry64FormatQSettings::Registry32Format を適切に指定する必要があるかもしれません。
  • 原因
    QSettings は、コンストラクタで指定された「組織名」と「アプリケーション名」に基づいて、プラットフォーム固有の場所に設定を保存・読み込みます。これらの名前が異なると、別の設定ファイル/場所を参照してしまいます。

b. beginGroup() で正しいグループに移動していない

  • トラブルシューティング
    • settings.beginGroup("MyGroup"); のように、目的のグループに移動しているか確認します。
    • グループ名をタイプミスしていないか、大文字・小文字を含め正確であるか確認します(特にmacOSやUnix系システムではキー名が大文字・小文字を区別します)。
    • beginGroup()endGroup() が正しくペアになっているか確認します。beginGroup() が複数回呼ばれて endGroup() が対応していない場合、想定外の深い階層にいる可能性があります。
  • 原因
    childKeys() は、現在のグループ直下のキーのみを返します。サブグループ内のキーを取得したい場合は、まずそのサブグループに beginGroup() で移動する必要があります。

c. 設定がまだ永続ストレージに保存されていない

  • トラブルシューティング
    • 設定を書き込んだ直後に読み込む場合、settings.sync() を呼び出して、強制的に永続ストレージに書き込みを行います。これにより、最新の設定が読み込み可能になります。
    • アプリケーション終了時に設定が保存されることを期待している場合は、QSettings オブジェクトが破棄される際に自動的に sync() が呼ばれます。しかし、クラッシュなどにより正常終了しなかった場合、設定が保存されないことがあります。
  • 原因
    QSettings::setValue() を呼び出しただけでは、すぐに設定がファイルやレジストリに書き込まれるとは限りません。Qtはパフォーマンスのために、ある程度の遅延を伴って書き込みを行います。
  • トラブルシューティング
    • 取得したいのがグループ名である場合は、settings.childGroups() を使用します。
  • 原因
    childKeys() は設定項目(キー)の名前を返しますが、childGroups() は子グループの名前を返します。ユーザーがグループを探索しようとして childKeys() を誤って使用していることがあります。

大文字・小文字の区別に関する問題 (特にクロスプラットフォーム開発で)

  • トラブルシューティング
    • 一貫性のあるキー名を使用する
      コード内で設定キーを参照する際は、常に同じ大文字・小文字の表記を使用するべきです。例えば、「UserName」と「username」を同じキーとして扱わないようにします。
    • QSettings::setCaseSensitivity() を使用して、明示的に大文字・小文字の区別を設定することもできますが、通常はデフォルトの動作に任せ、キー名の一貫性を保つのが推奨されます。
  • 原因
    • WindowsのレジストリやINIファイルではキー名の大文字・小文字は区別されません(通常)。
    • macOS (CFPreferences) や Unix系 (XDG) の設定ファイルでは、キー名の大文字・小文字が区別されます。
    • そのため、Windowsで開発したアプリケーションをmacOSに移植した場合などに、childKeys() が期待通りの結果を返さないことがあります。

ファイルアクセス権の問題

  • トラブルシューティング
    • アプリケーションを管理者権限(Windows)やsudo(Linux)で実行して、問題が解決するか確認します(これは一時的なデバッグ目的であり、本番環境では適切な権限で実行されるべきです)。
    • 設定ファイルのパスを確認し、そのディレクトリに対する書き込み権限があるか確認します。
    • QSettings::status() を呼び出して、設定オブジェクトの状態を確認します。QSettings::AccessErrorQSettings::FormatError などのエラーが返される場合があります。
  • 原因
    アプリケーションが設定ファイルやレジストリの特定の場所にアクセスする権限を持っていない場合、設定の読み書きができません。この場合、childKeys() も正しく機能しません。

INIファイル形式の特殊な挙動

  • トラブルシューティング
    • 手動で作成したINIファイルを使用する場合、INIファイルの構文が正しいことを確認します。特に [Group] の後にキーが続く形式になっているか。
    • INIファイル形式の場合、childKeys()[GroupName]Key=ValueKey の部分を返します。ルート直下にはキーが直接存在しないため、childKeys() は通常空のリストを返します。ルート直下のグループ名を取得したい場合は childGroups() を使用します。
  • 原因
    INIファイルはシンプルな構造ですが、QSettings がデフォルトで生成するINIファイルと、手動で作成したINIファイルでは、グループの扱いが異なる場合があります。
  • 最小限の再現コードを作成する
    問題が発生した場合、その問題が再現する最小限のコードスニペットを作成してみてください。これにより、問題を特定しやすくなります。
  • QSettings::sync() を意識的に呼び出す
    特に書き込みと読み込みが頻繁に行われる場合、sync() を呼び出すことで、データの一貫性を保ちやすくなります。
  • qDebug() を活用する
    • QSettings オブジェクトを構築した直後に、settings.fileName() を出力して、どのファイルが使用されているか確認します。
    • settings.group() を出力して、現在のグループを確認します。
    • settings.childKeys() の結果だけでなく、settings.childGroups() の結果も出力して、全体的な構造を把握します。
    • settings.allKeys() を使用して、設定オブジェクトが認識しているすべてのキーを(現在のグループに関係なく)取得してみるのも有効です。


例 1: 基本的な使用法 - 設定の書き込みと読み込み

この例では、階層的な設定を作成し、それぞれのグループで childKeys() を使ってキーの一覧を取得します。

#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // QSettingsが設定を保存する組織名とアプリケーション名を設定
    // これを設定しないと、システムデフォルトのパスに保存されるか、
    // QSettings::NativeFormatではプラットフォーム依存の挙動になる
    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    // QSettingsオブジェクトを作成
    QSettings settings;

    // --- 設定の書き込み ---
    qDebug() << "--- 設定を書き込み中 ---";

    // 一般設定
    settings.setValue("General/UserName", "Alice");
    settings.setValue("General/Locale", "ja_JP");
    settings.setValue("General/Theme", "Dark");

    // データベース設定
    settings.setValue("Database/Host", "localhost");
    settings.setValue("Database/Port", 5432);
    settings.setValue("Database/User", "admin");
    settings.setValue("Database/Password", "secret");

    // ネットワーク設定 (空のグループも作成可能)
    settings.beginGroup("Network");
    settings.endGroup(); // このグループにはまだキーがない

    // 設定を強制的に保存 (通常はQSettingsオブジェクト破棄時に自動的に行われる)
    settings.sync();
    qDebug() << "設定書き込み完了。ファイル名: " << settings.fileName();

    // --- 設定の読み込みとchildKeys()の使用 ---

    qDebug() << "\n--- ルートグループのキーを列挙 ---";
    // ルートグループ直下のキーは、通常存在しません
    // (QSettings::setValue("Key", Value) のように直接設定しない限り)
    // ここでは、子グループ (General, Database, Network) が存在します。
    QStringList rootChildKeys = settings.childKeys();
    if (rootChildKeys.isEmpty()) {
        qDebug() << "ルートグループには直接のキーがありません。";
    } else {
        qDebug() << "ルートグループの直接のキー:";
        foreach (const QString &key, rootChildKeys) {
            qDebug() << "- " << key;
        }
    }

    qDebug() << "\n--- Generalグループのキーを列挙 ---";
    settings.beginGroup("General"); // Generalグループに移動
    QStringList generalKeys = settings.childKeys();
    foreach (const QString &key, generalKeys) {
        qDebug() << "- " << key << ": " << settings.value(key).toString();
    }
    settings.endGroup(); // グループを抜ける

    qDebug() << "\n--- Databaseグループのキーを列挙 ---";
    settings.beginGroup("Database"); // Databaseグループに移動
    QStringList databaseKeys = settings.childKeys();
    foreach (const QString &key, databaseKeys) {
        qDebug() << "- " << key << ": " << settings.value(key).toString();
    }
    settings.endGroup(); // グループを抜ける

    qDebug() << "\n--- Networkグループのキーを列挙 ---";
    settings.beginGroup("Network"); // Networkグループに移動
    QStringList networkKeys = settings.childKeys();
    if (networkKeys.isEmpty()) {
        qDebug() << "Networkグループにはキーがありません。";
    } else {
        qDebug() << "Networkグループのキー:";
        foreach (const QString &key, networkKeys) {
            qDebug() << "- " << key << ": " << settings.value(key).toString();
        }
    }
    settings.endGroup();

    // 参考: すべてのキーをフラットなリストで取得
    qDebug() << "\n--- すべてのキーを列挙 (allKeys()) ---";
    QStringList allKeys = settings.allKeys();
    foreach (const QString &key, allKeys) {
        qDebug() << "- " << key << ": " << settings.value(key).toString();
    }

    return a.exec();
}

解説

  • allKeys() は、現在のグループに関わらず、すべてのグループ内のキーを「Group/SubGroup/Key」のような完全なパス形式で返します。
  • settings.sync() は、設定の変更をすぐに永続ストレージに書き込むために呼び出されます。通常、QSettings オブジェクトが破棄される際に自動的に行われますが、即座に反映させたい場合や、クラッシュ対策として明示的に呼び出すことがあります。
  • settings.endGroup() で現在のグループから抜け、1つ上の階層に戻ります。beginGroup()endGroup() はセットで使用することが重要です。
  • settings.beginGroup("GroupName") で特定のグループに移動し、そのグループの直下にあるキーを childKeys() で取得します。
  • settings.setValue("Group/Key", Value) の形式で値を設定すると、自動的にグループが作成されます。
  • QCoreApplication::setOrganizationName()setApplicationName() は、設定がどこに保存されるかを決定するために非常に重要です。これらが異なると、設定は異なる場所に保存され、期待通りに読み書きできない可能性があります。

例 2: 既存の設定ファイルを探索し、キーと値を表示する

この例では、既知のINIファイルを読み込み、その中のグループとキーを探索して表示します。

settings.ini ファイルの内容 (手動で作成または前の例で生成)

[General]
UserName=Alice
Locale=ja_JP
Theme=Dark

[Database]
Host=localhost
Port=5432
User=admin
Password=secret

[Network]

C++ コード

#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>
#include <QFileInfo> // ファイルの存在チェックのため

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString iniFilePath = "settings.ini"; // 実行ファイルと同じディレクトリにあると仮定

    // INIファイルを明示的に指定してQSettingsを作成
    QSettings settings(iniFilePath, QSettings::IniFormat);

    // ファイルが存在するか確認
    if (!QFileInfo::exists(iniFilePath)) {
        qDebug() << "エラー: 設定ファイルが見つかりません: " << iniFilePath;
        qDebug() << "このプログラムを実行する前に、" << iniFilePath << " を作成してください。";
        qDebug() << "(例1のコードを実行すると自動生成されます)";
        return 1; // エラー終了
    }

    qDebug() << "--- 設定ファイルを読み込み中: " << settings.fileName() << " ---";

    // ルートグループのキーとグループを探索
    qDebug() << "\n--- ルートレベルのグループを列挙 (childGroups()) ---";
    QStringList topLevelGroups = settings.childGroups();
    if (topLevelGroups.isEmpty()) {
        qDebug() << "ルートレベルにグループがありません。";
    } else {
        foreach (const QString &groupName, topLevelGroups) {
            qDebug() << "Found Group: [" << groupName << "]";

            settings.beginGroup(groupName); // 各グループに移動
            QStringList keysInGroup = settings.childKeys(); // グループ内のキーを取得

            if (keysInGroup.isEmpty()) {
                qDebug() << "  (このグループにはキーがありません)";
            } else {
                foreach (const QString &key, keysInGroup) {
                    qDebug() << "  - " << key << ": " << settings.value(key).toString();
                }
            }
            settings.endGroup(); // グループから抜ける
        }
    }

    qDebug() << "\n--- ルートレベルの直接のキーを列挙 (childKeys()) ---";
    // INIファイルの場合、通常ルートレベルに直接のキーは存在しません
    QStringList rootKeys = settings.childKeys();
    if (rootKeys.isEmpty()) {
        qDebug() << "INIファイルのルートには直接のキーは通常ありません。";
    } else {
        qDebug() << "ルートの直接のキー:";
        foreach (const QString &key, rootKeys) {
            qDebug() << "- " << key << ": " << settings.value(key).toString();
        }
    }

    return a.exec();
}
  • INIファイルでは、ルートレベルに直接キーが存在することは稀です。そのため、settings.childKeys() を直接呼び出しても、ほとんどの場合は空のリストが返されます。
  • この例では、まず childGroups() でトップレベルのグループ名を取得し、それぞれのグループに beginGroup() で移動してから childKeys() を呼び出しています。これは、INIファイル形式で階層的な設定を探索する一般的なパターンです。
  • QFileInfo::exists() でファイルが存在するかを事前にチェックし、エラーハンドリングをします。
  • QSettings(const QString &fileName, QSettings::Format format) コンストラクタを使用して、特定のINIファイルを読み込みます。


以下に、childKeys() の代替となる主な方法とその利用シーンを説明します。

QSettings::allKeys()

QSettings::allKeys() は、childKeys() の最も直接的な代替手段であり、より広範囲の情報を取得できます。

  • childKeys() との違い
    • childKeys() は現在のグループ直下のキーのみを相対パスで返します。
    • allKeys() は現在のグループに関係なく、すべてのキーを / 区切りの完全なパスで返します。
  • 利用シーン
    • 設定ファイルやレジストリ内のすべての設定項目を、階層構造を意識せずにフラットなリストとして取得したい場合。
    • アプリケーションのすべての設定をダンプしたり、設定の移行ツールを作成したりする場合。
    • 特定のキーが設定ファイル内のどこに存在するかを検索したい場合。
  • 機能
    QSettings オブジェクトが認識しているすべてのキー(設定項目名)を、完全なパス形式でリストとして返します。現在のグループに依存しません。


#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    QSettings settings;

    // 設定を書き込む
    settings.setValue("General/UserName", "Alice");
    settings.setValue("General/Locale", "ja_JP");
    settings.setValue("Database/Host", "localhost");
    settings.setValue("Database/Port", 5432);

    settings.sync();

    qDebug() << "--- allKeys() で全てのキーを列挙 ---";
    QStringList allKeys = settings.allKeys();
    foreach (const QString &keyPath, allKeys) {
        qDebug() << "Key: " << keyPath << ", Value: " << settings.value(keyPath).toString();
    }

    qDebug() << "\n--- childKeys() と比較 (ルートグループ) ---";
    QStringList rootChildKeys = settings.childKeys();
    if (rootChildKeys.isEmpty()) {
        qDebug() << "ルートグループには直接のキーがありません (allKeys() とは異なる)。";
    }

    qDebug() << "\n--- Generalグループに移動してchildKeys() ---";
    settings.beginGroup("General");
    QStringList generalChildKeys = settings.childKeys();
    foreach (const QString &key, generalChildKeys) {
        qDebug() << "General/" << key << ": " << settings.value(key).toString();
    }
    settings.endGroup();

    return a.exec();
}

出力例

--- allKeys() で全てのキーを列挙 ---
Key:  "Database/Host" , Value:  "localhost"
Key:  "Database/Port" , Value:  "5432"
Key:  "General/Locale" , Value:  "ja_JP"
Key:  "General/UserName" , Value:  "Alice"

--- childKeys() と比較 (ルートグループ) ---
ルートグループには直接のキーがありません (allKeys() とは異なる)。

--- Generalグループに移動してchildKeys() ---
General/ Locale :  "ja_JP"
General/ UserName :  "Alice"

QSettings::childGroups() と組み合わせた再帰的な探索

childKeys() は現在のグループのキーのみを返しますが、childGroups() と組み合わせることで、設定階層全体を再帰的に探索し、すべてのキーとグループを取得できます。これは allKeys() が提供するフラットなリストよりも、構造を維持した形で情報が必要な場合に特に有効です。

  • 利用シーン
    • 設定のツリービューを表示するUIを構築する場合。
    • 特定のグループやそのサブグループ内のすべての設定を処理する必要がある場合。
    • 設定のバックアップやリストア機能を実装する場合。
  • 機能
    childGroups() は現在のグループ直下にある子グループの名前をリストとして返します。これと childKeys() を再帰的に使用することで、設定のツリー構造を辿ることができます。


#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>

// 設定を再帰的に探索して表示する関数
void listSettingsRecursively(QSettings &settings, const QString &currentPath = "")
{
    // 現在のグループのキーを列挙
    QStringList keys = settings.childKeys();
    foreach (const QString &key, keys) {
        qDebug() << "  " << currentPath << key << " = " << settings.value(key).toString();
    }

    // 現在のグループの子グループを列挙し、それぞれを再帰的に探索
    QStringList groups = settings.childGroups();
    foreach (const QString &group, groups) {
        QString nextPath = currentPath + group + "/";
        qDebug() << "\nGroup: [" << nextPath << "]";
        settings.beginGroup(group); // 子グループに移動
        listSettingsRecursively(settings, nextPath); // 再帰呼び出し
        settings.endGroup();       // 子グループから抜ける
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    QSettings settings;

    // 設定を書き込む (例1と同じ)
    settings.setValue("General/UserName", "Alice");
    settings.setValue("General/Locale", "ja_JP");
    settings.setValue("Database/Host", "localhost");
    settings.setValue("Database/Port", 5432);
    settings.setValue("Database/Credentials/User", "admin"); // さらに深い階層
    settings.setValue("Database/Credentials/Password", "secret");

    settings.sync();

    qDebug() << "--- 設定を再帰的に列挙 ---";
    listSettingsRecursively(settings);

    return a.exec();
}

出力例

--- 設定を再帰的に列挙 ---

Group: [ Database/ ]

Group: [ Database/Credentials/ ]
   Database/Credentials/User  =  "admin"
   Database/Credentials/Password  =  "secret"

Group: [ General/ ]
   General/Locale  =  "ja_JP"
   General/UserName  =  "Alice"

QSettings::contains() と特定のキーパス

childKeys() を使ってキーを探索するのではなく、特定のキーが存在するかどうかを直接確認したい場合は QSettings::contains() を使用できます。

  • childKeys() との違い
    childKeys() は列挙目的ですが、contains() は単一のキーの存在確認に特化しています。
  • 利用シーン
    • アプリケーション起動時に、特定の必須設定が存在するかどうかを確認する場合。
    • 設定ダイアログなどで、ユーザーが値を入力する前にデフォルト値を設定する必要があるかどうかを判断する場合。
  • 機能
    指定された完全なキーパス(例: "General/UserName")が存在するかどうかをブール値で返します。


#include <QCoreApplication>
#include <QSettings>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    QSettings settings;

    settings.setValue("General/UserName", "Alice");
    settings.sync();

    qDebug() << "--- 特定のキーの存在確認 ---";

    if (settings.contains("General/UserName")) {
        qDebug() << "'General/UserName' は存在します。値: " << settings.value("General/UserName").toString();
    } else {
        qDebug() << "'General/UserName' は存在しません。";
    }

    if (settings.contains("General/NonExistentKey")) {
        qDebug() << "'General/NonExistentKey' は存在します。";
    } else {
        qDebug() << "'General/NonExistentKey' は存在しません。";
    }

    // グループに移動してからcontains()を使う場合
    settings.beginGroup("General");
    if (settings.contains("UserName")) { // beginGroupしているので、キー名のみでOK
        qDebug() << "Generalグループ内で 'UserName' は存在します。値: " << settings.value("UserName").toString();
    }
    settings.endGroup();

    return a.exec();
}

出力例

--- 特定のキーの存在確認 ---
'General/UserName' は存在します。値:  "Alice"
'General/NonExistentKey' は存在しません。
Generalグループ内で 'UserName' は存在します。値:  "Alice"

QSettings は、配列のような構造を保存するための特別なメソッドも提供しています。childKeys() は通常のキーを列挙しますが、配列の要素を直接列挙するわけではありません。配列を扱う場合はこれらのメソッドを使用します。

  • 利用シーン
    • 過去に開いたファイルリスト(最近使ったファイル)などの、可変長のリソースリストを保存・読み込みする場合。
    • 複数の同じ構造を持つ設定項目(例: 複数のプリンター設定)を扱う場合。
  • 機能
    • beginReadArray(prefix): 配列の読み込みを開始し、配列内の要素数を返します。
    • beginWriteArray(prefix, size): 配列の書き込みを開始します。
    • setArrayIndex(index): 現在の配列の要素インデックスを設定します。
    • endArray(): 配列の処理を終了します。


#include <QCoreApplication>
#include <QSettings>
#include <QStringList>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyApp");

    QSettings settings;

    // --- 配列の書き込み ---
    QStringList recentFiles;
    recentFiles << "/home/user/document1.txt"
                << "/home/user/image.png"
                << "/home/user/project.pro";

    settings.beginWriteArray("RecentFiles"); // 配列の書き込みを開始
    for (int i = 0; i < recentFiles.size(); ++i) {
        settings.setArrayIndex(i); // 配列のインデックスを設定
        settings.setValue("Path", recentFiles.at(i)); // 各要素のキーと値を設定
    }
    settings.endArray(); // 配列の書き込みを終了

    settings.sync();

    qDebug() << "--- 配列からキーを列挙 (childKeys() では見えない) ---";
    settings.beginGroup("RecentFiles");
    QStringList recentFileKeys = settings.childKeys(); // ここでは "Path" しか見えない
    qDebug() << "RecentFiles グループの childKeys(): " << recentFileKeys;
    settings.endGroup();


    qDebug() << "\n--- 配列の読み込み ---";
    int size = settings.beginReadArray("RecentFiles"); // 配列の読み込みを開始
    qDebug() << "保存された最近のファイル数: " << size;
    for (int i = 0; i < size; ++i) {
        settings.setArrayIndex(i); // 配列のインデックスを設定
        qDebug() << "  File " << i << ": " << settings.value("Path").toString();
    }
    settings.endArray(); // 配列の読み込みを終了

    return a.exec();
}

出力例

--- 配列からキーを列挙 (childKeys() では見えない) ---
RecentFiles グループの childKeys():  ("Path")

--- 配列の読み込み ---
保存された最近のファイル数:  3
  File  0 :  "/home/user/document1.txt"
  File  1 :  "/home/user/image.png"
  File  2 :  "/home/user/project.pro"

この例からもわかるように、childKeys() は配列内の個々の要素 (Path など) は示しますが、配列全体としての構造やそのインデックスは直接は示しません。配列を扱う場合は、beginReadArray() / beginWriteArray()setArrayIndex() が主要な手段となります。

QSettings::childKeys() は特定のグループ内の直接の子キーを列挙するのに適していますが、より柔軟な設定の探索や操作が必要な場合は、以下の代替方法を検討してください。

  • beginReadArray() / beginWriteArray()
    配列のような構造を保存・読み込みたい場合。
  • contains()
    特定のキーが存在するかどうかを直接確認したい場合。
  • childGroups() と組み合わせた再帰的探索
    設定の階層構造を維持したまま、すべてのキーとグループを探索したい場合。
  • allKeys()
    設定全体をフラットなリストとして取得したい場合。