Qt:从应用程序/可执行目录获取设置 ini 文件的问题
Posted
技术标签:
【中文标题】Qt:从应用程序/可执行目录获取设置 ini 文件的问题【英文标题】:Qt: Issue getting the settings ini file from application/executable directory 【发布时间】:2016-10-28 11:36:22 【问题描述】:我在 Windows7 上使用 Qt5.7。 在我当前的应用程序中,我有自己的设置管理器类,如下所示:
标题:
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
文件,因此它没有正常工作。 .
所以,问题是:如何修改上面的代码,以便能够从应用程序/可执行目录中获取settings.ini
文件?显然,settings.ini
文件始终与应用程序本身位于同一文件夹中。
【问题讨论】:
您似乎没有使用绝对路径。 我尝试了类似( QCoreApplication::applicationDirPath() + "/settings.ini" )
的方法,但没有成功。它说的是:请先实例化 QApplication 对象...
你应该有一个QApplication
或QCoreApplication
在你的主要地方。在调用静态函数之前,您必须先创建对象。无论如何,您都必须创建一个,所以这没什么大不了的。
main
中有一个对象...
您正试图在main
开始运行之前使用设置系统。那是因为您在某处使用设置来初始化全局变量:保证在输入 main
之前初始化这些设置。所以不要那样做,你会没事的。
【参考方案1】:
看到所有非静态成员函数和所有静态数据成员的对象似乎有点奇怪。您是否像SettingsManager()::read(...)
一样使用它?
只使用命名空间中的函数或单例模式可能更合适。
不管怎样,回到问题,你可以使用QApplication::applicationDirPath()来达到这个目的。它获取包含应用程序二进制文件的目录的绝对路径。例如
QString absPath = QDir(QApplication::applicationDirPath()).filePath("settings.ini");
获取到您想要的位置的绝对路径。
edit: - 回复关于“QApplication 不存在错误”的评论
您似乎对此有疑问,因为您在全局静态初始化程序中使用它,该初始化程序在进入 main() 之前运行,因此还没有 QApplication。您可以使用静态函数变量来延迟初始化,直到调用该函数。
您可以选择制作单例 SettingsManager,也可以只制作 QSettings(我认为 QSettings 可能像我上面所说的更奇怪)。
QSettings 单例示例:(需要在cpp中定义)
QSettings& globalInstance()
static QSettings settings(QDir(QApplication::applicationDirPath()).filePath("settings.ini"));
return settings;
如果你在你的函数中使用它,它不会创建一个 QSettings 直到你调用了这个函数,然后会有一个 QApplication 实例。但我更愿意让整个班级单身:
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");
【讨论】:
我通常会尽量避免所有看起来像 `ClassName::instance()' 的东西,比如单例或类似的风格,因为它看起来不合适(C++ 中的一些怪异)。如果可能的话,我更喜欢单态——至少它看起来是 C++。这并不意味着我不欣赏您的想法/建议,相反:拇指/投票!谢谢人:) 在这种情况下,我将使用namespace Settings read(..); write(..);
,并在 cpp 中为全局 QSettings 实例函数使用匿名命名空间。这样接口就Settings::read("key")
,看起来干净多了。或者把实例函数放在类外,即settings().read("key");
周末我没有构建环境。我今天早上在办公室尝试了上面的代码,但它似乎不是 100% 正确:我收到以下错误:filePath is not a member of QString
... 丹麦的东西很烂 :)
哎呀...我的代码中有 QDir appDir = QApplication::applicationDirPath();
并假设它会起作用。隐式转换是邪恶的......【参考方案2】:
您可以使用QSettings::setPath
设置设置路径
所以
QSettings::setPath(QSettings::IniFormat,QSettings::SystemScope,
QCoreApplication::applicationDirPath());
应该做的伎俩。
因为您似乎有一个 ini 文件,而不是每个用户群,我认为SystemScope
适合这里
注意:这将设置此位置 Qt 在您的程序中为SystemScope
查找 所有 ini 文件,因此如果您想要多个 ini,请不要使用它SystemScope
的文件位置
【讨论】:
事实上,应用程序还使用了其他 4 个 INI 文件,但位于一些不同的子文件夹中(这些用于获取某些输入数据文件的当前版本)。如果有的话,您的解决方案/想法将如何影响他们?无论如何,谢谢分享你的想法。竖起大拇指! :) 这会改变 Qt 查找 ini 文件的路径,所以它可能会。但是无论如何我会说你应该把你的文件放在一个中心位置。 (或系统文件的一个地方为每个用户配置另一个地方) 现有的 INI 文件不能放在一起。但我想它们仍然可以像指定路径和文件名一样被显式访问......?我的意思是不必以某种方式干扰上述QSetting::setPath
等。
请记住,系统范围内安装的程序可能没有对其安装目录的写入权限。因此,您要么要求每个用户自己安装它,要么将设置写入每个用户的配置位置,请参阅QStandardPaths::writableLocation()
首先启动将复制安装的设置,或者您甚至可以使用 Qt 资源将默认设置构建到应用程序中系统
我今天尝试了上面的建议,但不幸的是它没有奏效......【参考方案3】:
您不应将 ini 文件与您的应用程序一起发送。当用户第一次启动应用程序时,应用程序将创建 ini 文件。当您阅读您的设置时,您应该始终设置一个默认值。为了将来使用,用户将覆盖默认值并使用保存的设置。
改变你的阅读功能:
QVariant SettingsManager::read(const QString & key, const QVariant &defaultValue) const
return settings.value(key,defaultValue);
无论您在何处调用该函数,始终提供默认值
【讨论】:
不完全是我想要的,但它可能对未来的开发很有用。竖起大拇指:)以上是关于Qt:从应用程序/可执行目录获取设置 ini 文件的问题的主要内容,如果未能解决你的问题,请参考以下文章