一、代码之路
日常中,我们会使用QSettings来读取配置文件中的数据信息或者是注册表中的键值对信息,如下方代码:
QString strFilePath = "D:/my.ini";
QSettings sysSettings(strFilePath, QSettings::IniFormat);
sysSettings.setIniCodec("UTF-8");
sysSettings.beginGroup("MyInfo");
strHost = sysSettings.value("Name").toString();
strPort = sysSettings.value("Age").toString();
sysSettings.endGroup();
但是如果我们只是QSettings对象来存储数据,如下方代码中getMyInfo方法将自己的数据信息存储在QSettings对象中,但是我们发现在test方法中我们使用qDebug打印出来的名字和年龄都是空值。
Name: “” Age: 0
QSettings* getMyInfo(QString name, int age)
{
QSettings* settings = new QSettings();
settings->setValue("Name", name);
settings->setValue("Age", age);
return settings;
}
void testSettings()
{
QSettings* mySettings = getMyInfo("小明", 18);
QString name = mySettings->value("Name").toString();
int age = mySettings->value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
那么原因出在哪里呢?
简单看下Qt助手中这段解释说明:
QSettings objects can be created either on the stack or on the heap (i.e. using new). Constructing and destroying a QSettings object is very fast.
If you use QSettings from many places in your application, you might want to specify the organization name and the application name using QCoreApplication::setOrganizationName() and QCoreApplication::setApplicationName(), and then use the default QSettings constructor:
QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
...
QSettings settings;
如果我们需要使用QSettings的默认构造函数,需要调用下面的代码,设置全局的OrganizationName:
QCoreApplication::setOrganizationName("MySoft");
QSettings* settings = new QSettings("MySoft");
注意点:
如果没有全局设置OrganizationName,我们可以在QSettings构造方法中传入OrganizationName,下面代码中我们稍加修改,在getMyInfo方法中我们直接在栈上创建QSettings对象(即局部变量,会在函数结束后销毁),然后我们在testSettings方法中直接在QSettings对象中传入相同的OrganizationName,然后依旧可以输出我们传入的值,说明可以直接通过指定OrganizationName来创建一个全局的QSettings数据对象。
void getMyInfo(QString name, int age)
{
QSettings settings("MySoft");
settings.setValue("Name", name);
settings.setValue("Age", age);
}
void testSettings()
{
// 这里直接调用;
getMyInfo("小明", 18);
// 这里也是在构造中指定getMyInfo方法中同样的OrganizationName;
QSettings mySettings("MySoft");
QString name = mySettings.value("Name").toString();
int age = mySettings.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
那我们是不是可以通过指定不同的OrganizationName,来创建多个全局的QSettings数据对象呢,来看下方测试代码:
void testSettings()
{
// 测试数据
{
QSettings settings("MySoft1");
settings.setValue("Name", "小明");
settings.setValue("Age", 18);
QSettings settings1("MySoft2");
settings1.setValue("Name", "小李");
settings1.setValue("Age", 20);
}
{
QSettings mySettings1("MySoft1");
QString name = mySettings1.value("Name").toString();
int age = mySettings1.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
{
QSettings mySettings2("MySoft2");
QString name = mySettings2.value("Name").toString();
int age = mySettings2.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
}
输出结果:
Name: “小明” Age: 18
Name: “小李” Age: 20
通过测试,证明了我们的猜想。
其实这里除了OrganizationName之外,还有另外一个参数ApplicationName可以设置,请看下方测试代码:
void testSettings()
{
{
QSettings settings("MySoft", "Test1");
settings.setValue("Name", "小明");
settings.setValue("Age", 18);
QSettings settings1("MySoft", "Test2");
settings1.setValue("Name", "小李");
settings1.setValue("Age", 20);
}
{
QSettings mySettings1("MySoft", "Test1");
QString name = mySettings1.value("Name").toString();
int age = mySettings1.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
{
QSettings mySettings2("MySoft", "Test2");
QString name = mySettings2.value("Name").toString();
int age = mySettings2.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
{
// 这里特意增加了ApplicationName为Test3,实际未设置过ApplicationName为Test3
QSettings mySettings3("MySoft", "Test3");
QString name = mySettings3.value("Name").toString();
int age = mySettings3.value("Age").toInt();
qDebug() << "Name:" << name << " Age:" << age;
}
}
实际输出:
Name: “小明” Age: 18
Name: “小李” Age: 20
Name: “小明” Age: 18
从测试结果中看到,可以通过OrganizationName和ApplicationName组合进行使用,获取到不同的QSettings配置信息;
同时我特意增加了一组QSettings mySettings3(“MySoft”, “Test3”);测试数据,这里并未设置ApplicationName为Test3对应的数据,这里可以从源码中来寻找更加准确的答案,这里我们通过测试数据来得出的信息,源码的逻辑才是更加正确的。