阅读应用程序设置最佳实践

时间:2015-07-10 09:58:25

标签: c++ qt qsettings

在我的桌面应用中,我使用QSettings来保存各种应用程序值。例如,主表单位置,最近文档,连接参数以及一些改变应用程序行为方式的内容,例如“不再在信息对话框中显示此消息”。

我通常的处理方法是在应用程序启动时将所有设置读入结构或对象,并在应用程序关闭时保存它们。

我还有一个对话框,可以让我编辑设置对象中的许多值,并在对话框关闭时保存它们。

许多窗口和非可视对象都需要设置对象中的值。

这样做的最佳方式是什么?

我已经开始将设置对象作为主窗口的成员,但后来我遇到了其他窗口需要访问主窗口成员的问题。

我确实认为我可以在自己的cpp文件中创建设置对象,只需#include需要的地方。但我不确定这是否可能或它的语法。

此方案的最佳做法是什么?

3 个答案:

答案 0 :(得分:6)

我建议始终使用QSettings,避免使用补充结构或类。您可以在主服务器中设置应用程序名称组织名称 organization domanin

来自QtDocs:

  

如果您在应用程序的许多地方使用QSettings,您可能希望使用QCoreApplication :: setOrganizationName()和QCoreApplication :: setApplicationName()指定组织名称和应用程序名称,然后使用默认的QSettings构造函数:< / p>

QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");

然后使用默认构造函数,您需要在其中加入属性:

QSettings settings;
  

QSettings对象可以在堆栈上或堆上创建(即使用new)。构造和销毁QSettings对象非常快。

您可以在程序中的任何位置设置设置:

  

如果已存在具有相同键的设置,则新值将覆盖现有值。为了提高效率,可能无法立即将更改保存到永久存储中。 (您始终可以调用sync()来提交更改。)

您也可以在不同的线程中使用它而不会出现问题:

  

QSettings是可重入的。这意味着您可以同时在不同的线程中使用不同的QSettings对象。即使QSettings对象引用磁盘上的相同文件(或系统注册表中的相同条目),此保证仍然有效。如果通过一个QSettings对象修改了设置,则更改将立即在任何其他QSettings对象中可见,这些对象在同一位置上运行并且位于同一进程中。

     

QSettings可以安全地用于不同的进程(可以是同时运行的应用程序的不同实例或完全不同的应用程序)来读取和写入相同的系统位置。它使用建议文件锁定和智能合并算法来确保数据完整性。请注意,sync()会导入其他进程所做的更改(除了从此QSettings写入更改之外)。

答案 1 :(得分:6)

QSettings不是线程安全的。文件清楚地说明了这一点:

  

QSettings是可重入的。这意味着您可以使用不同的QSettings   同时在不同的线程中对象。这种保证是平等的   当QSettings对象引用磁盘上的相同文件时(或到   系统注册表中的相同条目。)

它是可重入但不是线程安全的。您无法安全地从多个线程使用全局QSettings对象。如果一个线程调用beginGroup()然后第二个线程也调用beginGroup(),那么你就会遇到问题,因为你的QSettings对象有错误的前缀。

对同一文件使用多个QSettings对象是线程安全的。因此,您应该在堆栈本地创建QSettings对象,而不是全局共享单个对象以避免竞争条件。

答案 2 :(得分:1)

我没有看到问题。

有两个基本选项:

  1. 创建一个对象并将其传递给所有窗口: 为简单起见,我们假设您的设置对象是Qsettings类型。另外,我们假设您的应用程序不是多线程的。 您可以在main函数中创建此对象,并将其作为参数传递给您创建的每个窗口。所有窗口都将#include <QSettings>并知道如何访问它。如果您有自己的设置类,也是如此。接口在它自己的头文件中,并且在它自己的cpp中实现。您创建一个并将其传递给所有窗口。
  2. 如评论中所述,您也可以使用singelton。只需为设置类创建一个静态函数,该函数返回在函数内声明为static的同一实例。 像这样:
  3. 
    class Settings
    {
    public:
        static Settings & TheSettings()
        {
            static Settings theSettings_;
            return theSettings_;
        }
        // Here go all methods for accessing the data
        // You will also want:
        ~Settings();
        Settings(const Settings &);
        Settings & operator=(const Settings &);
        // If you are using c++11 you may also want to add move constructor and assignment. 
        // Or you can just use the defaults for all the above if all your private members can destruct themselves  
    private:
        Settings();
    };
    

    以上是QSettings作为设置对象:

    
    class Settings
    {
    public:
        static QSettings & TheSettings()
        {
            static QSettings theSettings_;
            return theSettings_;
        }
    
    private:
        Settings();
        Settings(const Settings &);
        Settings & operator=(const Settigns &);
    };
    

    希望这能让你走上正轨

    PS。对于多线程应用,请确保在关键部分(或互斥保护)内访问Settings对象中的所有内部数据

    PPS。请注意,Miki在评论中提到QSettings是线程安全的,因此您不必在关键部分包装对它的访问权限。但是,如果您要使用不同的底层存储(无论是文件,另一个容器),它可能是必要的。