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 文件位置,请不要使用它
我在 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