Доступ к QSettings в моем приложении

Я пытаюсь реализовать настройки приложения для своего приложения Qt. Я работаю с QSettings, создал такой экземпляр своего класса

settings = new QSettings(qApp->organizationName(), qApp->applicationName());

и задавался вопросом: как лучше всего получить доступ к моим настройкам через мое приложение?

Мне понадобится доступ к некоторым настройкам из разных классов, но я не знаю, нужно ли мне объявить и создать только один экземпляр QSettings и сделать его доступным везде, где мне это нужно, или я могу создать локальные экземпляры QSettings там, где мне нужно получить доступ к некоторым настройкам.


person nmud    schedule 31.10.2017    source источник


Ответы (3)


Нет необходимости использовать синглтон, как сказано в документации Qt, QSettings:

Если вы используете QSettings из многих мест вашего приложения, вы можете указать имя организации и имя приложения, используя QCoreApplication::setOrganizationName() и QCoreApplication::setApplicationName(), а затем использовать конструктор QSettings по умолчанию:

Затем, после создания QApplication:

QApplication app(argc, argv);

Настройте различные параметры по умолчанию:

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

Когда вы хотите использовать QSettingsm, просто используйте конструктор по умолчанию, который берет параметры по умолчанию из основного приложения:

QSettings settings;
settings.setValue("example", 68);

В QML альтернативой является Настройки, настройки одинаковы, настройте приложение с графическим интерфейсом:

QGuiApplication app(argc, argv);
app.setOrganizationName("Some Company");
app.setOrganizationDomain("somecompany.com");
app.setApplicationName("Amazing Application");

И в QML настройте разные параметры:

Settings {
   property alias x: window.x
   property alias y: window.y
   property alias width: window.width
   property alias height: window.height
}
person mohabouje    schedule 31.10.2017
comment
Итак, пока я создаю локальные экземпляры с конструктором, указывающим имя организации и приложение, все в порядке? - person nmud; 31.10.2017
comment
@nmud После настройки QCoreApplication (обычно в вашей основной функции) вам нужно только использовать конструктор без параметров для QSettings везде, где вам нужны настройки. - person SirDarius; 31.10.2017
comment
Проблема будет в том, что qsettings использует пользовательский формат - person Swift - Friday Pie; 19.10.2020

На мой взгляд, лучший способ сделать это - реализовать шаблон проектирования Singleton для выделения объекта QSettings, но с учетом того, что если вы делитесь QSettings, вам приходится иметь дело с атомарным постоянством, я имею в виду, вам нужно будет иногда использовать sync() чтобы сохранить некоторые данные в ваших классах C++. Я понимаю, что вам не нужно использовать настройки в слое QML. Если это так, вы можете посмотреть qmlRegisterSingletonType< /strong>, чтобы использовать его в QML.

person Juan Garcia    schedule 31.10.2017
comment
Но нужен ли мне одноэлементный дизайн, если я создаю уникальный экземпляр QSettings в конструкторе моего главного окна? Мне просто нужно, чтобы предпочтения учитывались при следующем запуске приложения, поэтому мне, вероятно, также не нужно вызывать sync()? - person nmud; 31.10.2017
comment
@jgd да, это лучший выбор для доступа к глобальным настройкам с одноэлементным классом +1 - person saeed; 31.10.2017
comment
@nmud sync() вызывается сразу после сохранения. Вам нужно записать или просто прочитать настройки? - person Juan Garcia; 31.10.2017
comment
@jgd Мне нужно записать настройки из одного места и прочитать настройки из нескольких мест в моем коде - person nmud; 31.10.2017
comment
@nmud Хорошо, мой совет: используйте sync(), когда вы пишете, несмотря на то, что QSettings использует кэшированную память, поэтому, когда вы читаете в одном месте, настройки будут согласованными, но если ваше приложение выйдет из строя в середине выполнения, это может быть несовместимы в следующем исполнении. Кроме того, как я уже сказал, используйте для этого объекта одноэлементный дизайн. - person Juan Garcia; 31.10.2017

Чтобы иметь глобальные настройки во всем приложении, singleton может быть хорошей идеей, у меня есть шаблон для класса настроек, и я размещаю его здесь, возможно, он будет полезен вам и другим.

Здесь у меня есть класс GlobalSettings, который представляет собой синглтон, следующий за файлами заголовка и cpp.

заголовочный файл:

#ifndef GLOBALSETTINGS_H
#define GLOBALSETTINGS_H

#include <QSettings>
#include <QObject>

class GlobalSettings
{
public:
    Q_DISABLE_COPY(GlobalSettings)

    static GlobalSettings* getSettings();

    // Settings getter and setters

    QString Setting1() const;
    void setSetting1(const QString &Setting1);

    QString Setting2() const;
    void setSetting2(const QString &Setting2);

private:

    // private constructor
    GlobalSettings();
    static GlobalSettings * m_Settings;

    QSettings * settings;

    // Settings memebers
    QString m_Setting1;
    QString m_Setting2;

};

#endif // GLOBALSETTINGS_H

и файл cpp для GlobalSettings

#include "globalsettings.h"

#include <QCoreApplication>

GlobalSettings * GlobalSettings::m_Settings = NULL;

GlobalSettings::GlobalSettings()
{
    settings = new QSettings(qApp->organizationName(), qApp->applicationName());
    if (!settings->contains("Setting1"))
    {
        settings->setValue("Setting1","Something"); //  default value
    }
    else
    {
        m_Setting1 = settings->value("Setting1").toString();
    }

    if (!settings->contains("Setting2"))
    {
        settings->setValue("Setting2","Something"); //  default value
    }
    else
    {
        m_Setting2 = settings->value("Setting2").toString();
    }
    settings->sync();
}

GlobalSettings *GlobalSettings::getSettings()
{
    if (m_Settings == NULL)
    {
        m_Settings =  new GlobalSettings();
    }
    return m_Settings;
}

QString GlobalSettings::Setting1() const
{
    return m_Setting1;
}

void GlobalSettings::setSetting1(const QString &Setting1)
{
    m_Setting1 = Setting1;
    settings->setValue("Setting1",Setting1);
}

QString GlobalSettings::Setting2() const
{
    return m_Setting2;
}

void GlobalSettings::setSetting2(const QString &Setting2)
{
    m_Setting2 = Setting2;
    settings->setValue("Setting2",Setting2);
}

и вот как использовать его везде, где вы хотите использовать

#include "mainwindow.h"
#include <QApplication>

#include <QDebug>

#include <globalsettings.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    GlobalSettings * setting = GlobalSettings::getSettings();

    qDebug() <<  setting->Setting1();


    MainWindow w;
    w.show();

    return a.exec();
}

и теперь, если вы хотите иметь класс настроек потокобезопасности, вы можете заблокировать мьютекс в функциях get и setter

person saeed    schedule 31.10.2017
comment
Обязательно ли иметь для этого глобальную переменную? Мне не очень удобно работать с глобальными переменными, и если работа с локальными экземплярами работает, я бы предпочел это. - person nmud; 31.10.2017
comment
Сделаю. Кроме того, не является ли QSettings потокобезопасным? Зачем мне мьютекс, если это так? - person nmud; 31.10.2017