2015-07-10 45 views
3

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

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

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

值的目标将通过许多窗口,也许非可视化对象需要..

什么是做到这一点的最好方法是什么?

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

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

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

+0

为什么其他窗口访问主窗口的成员有问题? – user463035818

+0

为您的设置对象使用单例模式 – Zlatomir

+0

@ tobi30这样做会破坏初学者的封装原则,所以不是最佳实践。 –

回答

5

我建议总是使用QSettings,避免补充结构或类。您可以设置应用程序名称,组织名称组织domanin在您的主。

从QtDocs:

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

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

然后用你需要acceess属性的默认构造函数:

QSettings settings; 

QSettings对象可以在堆栈或堆上创建。使用新的)。构建和销毁QSettings对象非常快。

您可以设置在任何地方程序设置:

如果已经存在具有相同键的设置,现有的值被新的值覆盖。为了提高效率,这些更改可能不会立即保存到永久存储中。 (您可以随时调用同步()提交更改。)

你也可以用它在不同的线程没有问题:

QSettings是折返。这意味着你可以同时在不同的线程中使用不同的QSettings对象。即使QSettings对象引用磁盘上的相同文件(或系统注册表中的相同条目),此保证也会保留。如果通过一个QSettings对象修改设置,则该更改将立即在运行于同一位置且生活在同一进程中的任何其他QSettings对象中可见。

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

+0

感谢您的评论和回答@Miki我打算采用这种方法。 –

+0

@MichaelVincent很高兴帮助! – Miki

1

我看不到的问题。

有两种基本的选择:

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

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是线程安全的,因此您不必在关键部分中包装对它的访问权限。但是,如果您曾经使用过不同的底层存储(不管是文件还是其他容器),它可能都是必需的。

+0

1)为什么在使用QVariantMap时使用std :: map? 2)为什么要像QSettings一样用很多努力来实现相同的功能? – Miki

+0

这只是一个原理样本,但我固定它使用Qsettings –

+0

是的,我明白这一点。但仍然是我的问题:QSettings已经是线程安全的,你可以有多个实例没有问题,等等...为什么你需要比QSettings更多的东西? – Miki

5

QSettings不是线程安全的。该文件明确指出:

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

这是折返的,但不是线程安全的。您无法安全地使用来自多个线程的全局QSettings对象。如果线程调用beginGroup(),然后第二个线程也调用beginGroup(),那么你有问题,因为你的QSettings对象有错误的前缀。

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

相关问题