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

Reading application settings best practice

本文关键字:最佳 设置 应用程序      更新时间:2023-10-16

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

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

我也有一个对话框,使我能够编辑设置对象中的许多值,并在对话框关闭时保存它们。

设置对象中的值将被许多窗口和可能非可视对象所需要。

最好的方法是什么?

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

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

这个场景的最佳实践是什么?

我建议始终使用QSettings,避免使用补充结构体或类。您可以在main中设置应用程序名称组织名称组织域

从QtDocs:

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

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写入更改之外)。

QSettings不是线程安全的。文档说得很清楚:

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

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

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

我看不出问题。

有两个基本选项:

    创建一个对象并传递给所有的窗口:为了简单起见,我们假设您的settings对象是Qsettings类型。另外,我们假设您的应用程序不是多线程的。您可以在main函数中创建这个对象,并将其作为参数传递给创建的每个窗口。所有的窗口都将#include <QSettings>并知道如何访问它。如果您有自己的设置类,情况也是如此。接口在它自己的头文件中,实现在它自己的cpp文件中。您创建它并将其传递给所有窗口。
  1. 正如评论中提到的,你也可以使用单元素。只需为settings类创建一个静态函数,该函数返回在函数内部声明为静态的相同实例。像这样:

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 &);
};

希望这能让你走上正确的道路

p。对于多线程应用程序,确保你的设置对象中的所有内部数据都是在临界区(或互斥保护)内访问的

pp。请注意,正如Miki在评论中提到的,QSettings是线程安全的,所以你不必在临界区包装对它的访问。但是,如果您要使用不同的底层存储(无论是文件还是其他容器),则可能需要使用