R
May 10, 2017, 4:57 p.m.

Области видимости

Хочется создать в qt приложении класс settingsApp, который бы после загрузки приложения брал через QSettings(из реестра виндоус) в себя различные настройки и хранил их, передавал в различные функции, если надо. Но можно использовать наверное и просто QSettings. Но вопрос в том, где и как их создавать(экземпляры класса QSettings или settingsApp) чтобы они были доступны из всех мест программы? У меня в программе несколько отдельных виджетов.

#ifndef SETTINGS_H
#define SETTINGS_H

#include <Headers/ModBusUSB.h>
#include <QSettings>


class settingsClass
{
public:
    TConfigUSBPort configUSBDevice;
    int tresHold;
    settingsClass() {}
};
void readSettings(settingsClass &settingsDiesel);


#endif // SETTINGS_H
#include <Headers/settings.h>


settingsClass settingsDiesel;

void readSettings(settingsClass &settingsDiesel){
    QSettings *settings;
    settings = new QSettings;
    settingsDiesel.configUSBDevice.adc_count = settings->value("count").toInt();
    settingsDiesel.configUSBDevice.adc_freq = settings->value("freq").toInt();
    settingsDiesel.configUSBDevice.pid = settings->value("PID").toInt();
    settingsDiesel.configUSBDevice.vid = settings->value("VID").toInt();
    settingsDiesel.configUSBDevice.timeOut = settings->value("timeout").toInt();
    settingsDiesel.tresHold = settings->value("treshold").toInt();
}
Вот settings.h и .cpp, но объект settingsDiesel не доступен в widgetSettings Заголовок settings.h подключен в widgetSettings.h
#include <Headers/widgetsettings.h>
#include "ui_widgetsettings.h"

widgetSettings::widgetSettings(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::widgetSettings)
{
    ui->setupUi(this);
    QRegExp pid("[1-9]\\d{0,3}");
    QValidator *validatorPID = new QRegExpValidator(pid, this);

    ui->lineEditPID->setValidator(validatorPID);
    ui->lineEditVID->setValidator(validatorPID);
    ui->spinBoxCount->setMaximum(MAX_COUNT_ADC);
}



widgetSettings::~widgetSettings()
{
    delete ui;
}

void widgetSettings::on_pushButtonAccept_clicked()
{
    QSettings settings(ORGANIZATION_NAME, APPLICATION_NAME);
    bool ok;
    auto PID = QString("0x" + ui->lineEditPID->text()).toInt(&ok, 16);
    auto VID = QString("0x" + ui->lineEditVID->text()).toInt(&ok, 16);
    settings.setValue("PID", PID);
    settings.setValue("VID", VID);
    settings.setValue("timeout", ui->spinBoxTimeout->value());
    settings.setValue("freq", ui->spinBoxFreq->value());
    settings.setValue("count", ui->spinBoxCount->value());
    settings.setValue("treshold",ui->spinBoxTreshold->value());
    settings.sync();
}

structure.png
2

Do you like it? Share on social networks!

7
Evgenii Legotckoi
  • May 10, 2017, 8:36 p.m.

Итак. Первое, что стоит учитывать, это то, что если в функции main прописать следующее:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QCoreApplication::setOrganizationName( "ORGANIZATION" );
    QCoreApplication::setApplicationName( "APP NAME" );
    QCoreApplication::setApplicationVersion( APP_VERSION );

    MainWindow w;
    w.show();

    return a.exec();
}

то тогда не нужно будет каждый раз писать так

QSettings settings(ORGANIZATION_NAME, APPLICATION_NAME);

Достаточно будет записи

QSettings settings;

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

Но если имеется необходимость всё вывести в единый класс, который отвечал бы за настройки, то возможно имеет смысл использовать статические методы и даже... может быть синглтон.

Тогда сохранение настроек в диалоге настроек может выглядеть так:

void ConfigDialog::saveSettings()
{
    SettingsHelper::setCustomProjectsDirectory(ui->buildPage->isCustomDirectory());
    SettingsHelper::setPathCustomProjectsDirectory(ui->buildPage->getPathDirectory());
    emit settingsUpdated();
}

А сами эти методы могут выглядеть так:

Заголовочный файл:
class SettingsHelper
{
    static const QString CUSTOM_PROJECT_DIRECTORY;
    static const QString CUSTOM_PROJECT_DIRECTORY;

public:
    static void setCustomProjectsDirectory(const bool value);
    static void setPathCustomProjectsDirectory(const QString value);

    static bool isCustomProjectsDirectory();
    static QString getPathCustomProjectsDirectory();
};
Файл реализации:
const QString SettingsHelper::CUSTOM_PROJECT_DIRECTORY = "build_and_run/customProjectsDirectory";
const QString SettingsHelper::PATH_PROJECT_DIRECTORY = "build_and_run/pathProjectsDirectory";

void SettingsHelper::setCustomProjectsDirectory(const bool value)
{
    QSettings settings;
    settings.setValue(CUSTOM_PROJECT_DIRECTORY, value);
    settings.sync();
}

void SettingsHelper::setPathCustomProjectsDirectory(const QString value)
{
    QSettings settings;
    settings.setValue(PATH_PROJECT_DIRECTORY, value);
    settings.sync();
}

bool SettingsHelper::isCustomProjectsDirectory()
{
    QSettings settings;
    return settings.value(CUSTOM_PROJECT_DIRECTORY, false).toBool();
}

QString SettingsHelper::getPathCustomProjectsDirectory()
{
    QSettings settings;
    return settings.value(PATH_PROJECT_DIRECTORY, qApp->applicationDirPath()).toString();
}

Таким образом с помощью статических методов можно будет дергать параметры в любом месте программы и когда захочется. Достаточно будет добавить в нужном файле заголовочный файл stylehelper.h и воспользоваться статическими методами для получения необходимых настроек.

    R
    • May 11, 2017, 1:18 a.m.

    То есть для каждого значения(переменной), которое я хочу сохранить, надо реализовать статик-методы get и set? Я правильно понял? В синглтон пока рано лезть, хотя я тоже про него думал (прочитал в одной книжке и подумал, что это то, что мне надо).

      R
      • May 11, 2017, 1:30 a.m.

      У QSettings оказывается тоже есть статик-методы

      QSettings::setValue("VID", VID);
      QSettings::value("PID").toInt();
      . Может можно просто их использовать
        Evgenii Legotckoi
        • May 11, 2017, 9:29 a.m.

        Конечно, можно и эти методы использовать. Вообще, всё зависит от задачи. Если нужно дёрнуть одно значение, то можно и статическими методами QSettings воспользоваться. Если нужно брать пачку значений для какого-то специального объекта, то можно сделать обёртку с методом, который будет принимать в качестве аргумента ссылку или указатель на данный объект и добавлять в него все необходимые объекты.

          R
          • May 13, 2017, 7:20 p.m.

          Решил все таки сделать синглтон, я только не очень понимаю, где именно его создать, чтобы был доступ по всей программе?

            Evgenii Legotckoi
            • May 13, 2017, 10:37 p.m.
            • The answer was marked as a solution.

            Тут надо понимать, что такое Singleton (одиночка). Под синглтоном подразумевается класс, который имеет в программе только один экземпляр, который создаётся при первом обращении к нему, применительно к C++. Раз экземпляр в программе только один, значит объект в данном случае должен объявляться как static и обращение к нему должно быть сделано через статический метод. Например, можно использовать Синглтон Меерса

            #ifndef SINGLETONCLASS_H
            #define SINGLETONCLASS_H
            
            class SingletonClass
            {
            public:
                int getSomeInfo()
                {
                    return 10;
                }
            
                static SingletonClass& instance()
                {
                    static SingletonClass instance;
                    return instance;
                }
            
            private:
                SingletonClass(){}
            };
            
            #endif // SINGLETONCLASS_H

            В данном случае получение экземпляра класса всегда должно осуществляться через статический метод SingletonClass::instance() Все остальные методы могут быть не статическими. А применять его можно будет абсолютно везде, где будет подключён его заголовочный файл.

            #include "widget.h"
            #include <QApplication>
            #include <QDebug>
            
            #include "singletonclass.h"
            
            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                // Обращение к синглтону и его методу
                qDebug() << SingletonClass::instance().getSomeInfo();
            
                Widget w;
                w.show();
            
                return a.exec();
            }

            Только нужно поосторожнее работать с этим паттерном проектирования, поскольку иногда от него могут быть только проблемы. Особенно, если в какой-то момент понадобится иметь два и более экземпляров этого класса. Например, для нескольких настроек софта, которые могут быть применены для разных открытых документов. Перекраивать в таком случае крупный проект будет весьма затратно.

              R
              • May 13, 2017, 11:02 p.m.

              Я вроде все понял. Спасибо большое.

                Comments

                Only authorized users can post comments.
                Please, Log in or Sign up
                • Last comments
                • AK
                  April 1, 2025, 11:41 a.m.
                  Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
                • Evgenii Legotckoi
                  March 9, 2025, 9:02 p.m.
                  К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
                • VP
                  March 9, 2025, 4:14 p.m.
                  Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
                • ИМ
                  Nov. 22, 2024, 9:51 p.m.
                  Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                • Evgenii Legotckoi
                  Oct. 31, 2024, 11:37 p.m.
                  Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup