Qt:从 application/executable 目录获取设置 ini 文件时出现问题

Qt: Issue getting the settings ini file from application/executable directory

我在 Windows7.
上使用 Qt5.7 在我当前的应用程序中,我有自己的设置管理器 class,如下所示:

Header:

class SettingsManager
{
public:
    void     write(const QString & key, const QVariant & variant);
    QVariant read (const QString & key) const;

private:
    static QSettings settings;
};

来源 cpp:

QSettings SettingsManager::settings("settings.ini", QSettings::IniFormat);

void SettingsManager::write(const QString & key, const QVariant & variant)
{
    settings.setValue(key, variant);
}

QVariant SettingsManager::read(const QString & key) const
{
    return settings.value(key);
}

我的问题是:我把这个应用程序给了一些朋友,他们可能用不同的工作目录或其他东西启动了它,应用程序没有找到 settings.ini 文件,因此它没有像它应该...

所以,问题是:如何修改上面的代码才能从application/executable 目录中获取settings.ini 文件?显然,settings.ini 文件始终与应用程序本身位于同一文件夹中。

您不应随申请一起发送 ini 文件。当用户第一次启动应用程序时,应用程序将创建 ini 文件。当您阅读您的设置时,您应该始终设置一个默认值。为了将来使用,用户将覆盖默认值并使用保存的设置。

更改您的阅读功能:

QVariant SettingsManager::read(const QString & key, const QVariant &defaultValue) const
{
    return settings.value(key,defaultValue);
}

无论您在哪里调用该函数,始终提供默认值

看到一个对象全是非静态成员函数,全是静态数据成员,似乎有点奇怪。你像SettingsManager()::read(...)一样使用它吗? 只使用命名空间中的函数或单例模式可能更合适。

无论如何,回到问题,你可以使用 QApplication::applicationDirPath() 来达到这个目的。它获取包含应用程序二进制文件的目录的绝对路径。例如

QString absPath = QDir(QApplication::applicationDirPath()).filePath("settings.ini");    

获取到达所需位置的绝对路径。

编辑:- 回复关于 "QApplication doesn't exist error"

的评论

您似乎对此有疑问,因为您在全局静态初始化器中使用它,在进入 main() 之前 运行,因此还没有 QApplication。您可以使用静态函数变量来延迟初始化,直到函数被调用。

您可以选择创建一个单独的 SettingsManager,或者只创建 QSettings(我认为 QSettings 可能像我上面说的那样更奇怪)。

QSettings 单例示例:(需要在 cpp 中定义)

QSettings& globalInstance() {
    static QSettings settings(QDir(QApplication::applicationDirPath()).filePath("settings.ini"));
    return settings;
}

如果你在你的函数中使用它,它不会创建一个 QSettings 直到你调用这个函数,然后会有一个 QApplication 实例。但我更愿意将整个 class 设为单例:

settingsmanager.h:

#include <QApplication>
#include <QDir>
#include <QSettings>

class SettingsManager
{
public:
    SettingsManager & instance();

    void     write(const QString & key, const QVariant & variant);
    QVariant read (const QString & key) const;

private:
    SettingsManager(const QString & path) : 
        settings(path, QSettings::IniFormat)
    {}

    QSettings settings;
};

settingsmanager.cpp:

#include "settingsmanager.h"

SettingsManager& SettingsManager::instance() {
    static SettingsManager s(QDir(QApplication::applicationDirPath()).filePath("settings.ini"));
    return s;
}

void SettingsManager::write(const QString & key, const QVariant & variant)
{
    settings.setValue(key, variant);
}

QVariant SettingsManager::read(const QString & key) const
{
    return settings.value(key);
}

用法:

auto val = SettingsManager::instance().read("key");

设置路径可以用QSettings::setPath

所以

QSettings::setPath(QSettings::IniFormat,QSettings::SystemScope,
                  QCoreApplication::applicationDirPath());

应该可以解决问题。

因为你似乎有一个 ini 文件,而不是每个用户群,我认为 SystemScope 在这里是合适的

注意: 这将设置 Qt 在程序中查找 all ini 文件的位置 SystemScope 所以如果您想要 SystemScope

的多个 ini 文件位置,请不要使用它