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

Reading application settings best practice

在我的桌面应用程序中,我使用 QSettings 来保存各种应用程序值。例如,主窗体位置、最近的文档、连接参数和一些改变应用程序行为方式的东西,例如信息对话框上的 "don't show this message again"。

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

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

设置对象中的值将被许多 windows 和非可视对象所需要..

最好的方法是什么?

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

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

这种情况的最佳做法是什么?

我建议始终使用 QSettings,避免补充结构或 class。您可以在 main.application name, organization name, and organization domanin 中设置

]

来自 QtDocs:

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 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 there already exists a setting with the same key, the existing value is overwritten by the new value. For efficiency, the changes may not be saved to permanent storage immediately. (You can always call sync() to commit your changes.)

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

QSettings is reentrant. This means that you can use distinct QSettings object in different threads simultaneously. This guarantee stands even when the QSettings objects refer to the same files on disk (or to the same entries in the system registry). If a setting is modified through one QSettings object, the change will immediately be visible in any other QSettings objects that operate on the same location and that live in the same process.

QSettings can safely be used from different processes (which can be different instances of your application running at the same time or different applications altogether) to read and write to the same system locations. It uses advisory file locking and a smart merging algorithm to ensure data integrity. Note that sync() imports changes made by other processes (in addition to writing the changes from this QSettings).

我没看出问题所在。

有两个基本选项:

  1. 创建一次对象并将其传递给所有对象windows: 为了简单起见,我们假设您的设置对象是 Qsettings 类型。我们还假设您的应用程序不是多线程的。 您在主函数中创建此对象并将其作为参数传递给您创建的每个 window。所有 windows 都会 #include <QSettings> 并且知道如何访问它。如果您有自己的设置 class,也是如此。接口在它自己的头文件中,实现在它自己的 cpp 中。您创建一个并将其传递给所有 windows。
  2. 如评论中所述,您也可以使用单例。只需为设置 class 创建一个静态函数,returns 与在函数内部声明为静态的实例相同。 像这样:

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. 对于多线程应用程序,请确保在关键部分(或互斥保护)内访问设置对象中的所有内部数据

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

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

QSettings is reentrant. This means that you can use distinct QSettings object in different threads simultaneously. This guarantee stands even when the QSettings objects refer to the same files on disk (or to the same entries in the system registry).

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

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