在全局静态类中使用QSettings

时间:2015-06-02 20:48:11

标签: qt

我的任务是创建一个QSettings包装类(QML主要需要包装),我也可以从模型中到达任何地方。

显而易见的选择是此类的静态全局实例。然而问题是这种方法是在main被销毁之后它被销毁,因此给了我以下警告:

QApplication

这是一个简化的示例代码,显示了一个非常简单的包装器和销毁阶段:

QApplication::qAppName: Please instantiate the QApplication object first

打印出以下内容:

#include <QCoreApplication>
#include <QDebug>
#include <QGlobalStatic>
#include <QSettings>
#include <QTimer>

class Settings: public QObject
{
public:
    ~Settings() { qDebug() << "~Settings"; }
    QSettings settings;
};

Q_GLOBAL_STATIC(Settings, globalSettings)

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

    QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){qDebug() << "~QCoreApplication aboutToQuit";});
    QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){globalSettings->settings.setValue("Hi", 2);});
    QObject::connect(&app, &QCoreApplication::destroyed, [](){qDebug() << "~QCoreApplication destroyed";});

    QTimer::singleShot(0, &app, SLOT(quit()));

    return app.exec();
}

我的问题是:在我的计划~QCoreApplication aboutToQuit ~QCoreApplication destroyed ~Settings QApplication::qAppName: Please instantiate the QApplication object first 中提供QSettings后发出但在QCoreApplication::aboutToQuit之前使用,我该如何避免此警告?

1 个答案:

答案 0 :(得分:4)

使用QSettings

我已经在我曾经制作过的每个项目中使用QSettings。这是我倾向于使用它的模式:

在main.cpp

#include <QSettings>

//...

// Then in main(), after QApplication is instantiated, but before any settings are accessed

QSettings::setDefaultFormat(QSettings::IniFormat);
QApplication::setOrganizationName("MyOrg");
QApplication::setApplicationName("MyApp"):

然后,当您即将访问QSettings时,您只需执行此操作:

QSettings s;

s.value(// reading a value
s.setValue(// writing a value

所有内容都保存在INI文本文件的用户范围中。它将位于C:/Users/<username>/AppData/Roaming/MyOrg/MyApp.ini下的Windows中。

QSettings(恕我直言)的这种用法非常简洁,不需要全局变量或静态引用,而且非常快速有效。它非常易读。

现在,为了能够在适当的时间加载设置,而不是出现问题中提到的错误,请参阅以下链接中的初始示例:

http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application

http://doc.qt.io/qt-5/qtwidgets-mainwindows-application-example.html

它在Qt应用程序的时间轴上工作得更好,效果很好。我倾向于为我的大多数GUI类和一些后端类创建readSettingswriteSettings。当小部件的readSettings或构造函数发生且showEvent发生在writeSettings时,会发生closeEvent。此外,如果我有一个专用的设置对话框,我会在设置对话框写入这些特定设置后立即向readSettings发出一个信号,以便有任何受影响的类。

如果使用QSettings的QML端口,它还使用组织名称和应用程序名称以及QSettings的默认格式来选择其文件名和位置。

http://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html

我相信该QML组件的默认功能只是在创建组件时读取设置,并在QML更改时写入设置。因此,要从C ++更改它并让它被QML识别,您应该使用标准的QML / C ++方法,例如:

http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html

最后,如果我计划为构建决定的程序安装默认值而我不想对它们进行硬编码,我手写一个INI文件并让安装程序将它放在系统范围位置:C:/ProgramData/MyOrg/MyApp.ini

如果您的程序设置比您想要存储在INI文件中的设置更复杂,我会考虑使用QJson和SaveGame示例。

希望有所帮助。