Qt — виджет регулятора громкости звука

      Комментарии к записи Qt — виджет регулятора громкости звука отключены

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 6 мес. назад.

  • Автор
    Сообщения
  • #3181

    В статье про шаблон проектирования Singleton в качестве примера я использовал параметры (настройки программы), т.к. такие настройки должны существовать в программе в единственном экземпляре и к ним нужен доступ из самых различных мест программы (глобальная точка доступа). Напомню, что сами настройки — громкость звука, в данном случае, мы хранили в базе данных (см. статью про БД в библиотеке Qt и паттерн Фасад). В статье подробно описывается как создавать свои виджеты в Qt Designer — вы можете сделать по такому образцу что угодно (не только регулятор громкости).

    Итак, у нас есть шаблонный класс Singleton и класс Volume, который отвечает за параметры громкости звука. Мы можем обращаться к настройкам через Singleton<Volume>::instance(). Я пишу макрос для Singleton-а:
    #define VOLUME Singleton<Volume>::instance()

    Теперь в любой точке программы при проигрывании звука я могу обратиться к VOLUME и получить или изменить нужные параметры.

    Виджет со слайдером

    На странице настроек может быть удобно разместить регулятор громкости со слайдером:
    slidervolumecontroller

    Такой виджет я сделал в Qt Designer. Для этого нужно:

    • добавить в проект файл ресурсов;
    • добавить в в файл ресурсов любой префикс и файлы с изображениями — для иконки возле слайдера;
    • добавить класс формы Qt Designer — я назвал класс VolumeController, при этом были добавлены файлы volumecontroller.h, volumecontroller.cpp и volumecontroller.ui.
    • в файле интерфейса (при редактировании в Qt Designer) вытащить на форму QLabel (для отображения картинки) и QSlider. Добавить раскладку (менеджер размещения)через выпадающее меню, щелкнув по форме левой кнопкой мыши;
    • при редактировании в Qt Designer, для QLabel установить файл с изображением — свойство pixmap. Для этого нужно выбрать добавление файла из ресурса, а в появившемся окне выбрать нужную картинку (из тех, что добавили на предыдущем шаге):
      set_qlabel-pixmap

    Виджет готов, осталось написать код для нашего класса. В заголовочном файле можно ничего не менять, автоматически сгенерируется примерно такой код:
    #include

    namespace Ui {
      class VolumeController;
    }
    
    class VolumeController : public QWidget {
      Q_OBJECT
    public:
      explicit VolumeController(QWidget *parent = 0);
      ~VolumeController();
    private:
      Ui::VolumeController *ui;
    };

    В файле реализации надо изменить конструктор так, чтобы при создании объекта устанавливалась начальная громкость (положение слайдера) в соответствии с настройками, которые были сохранены в базе данных во время предыдущего сеанса работы, а также соединить сигналы перемещения слайдера со слотами изменения настроек громкости (и наоборот):

    #include "volumecontroller.h"
    #include "ui_volumecontroller.h"
    #include "settings_db/volume.h"
    
    VolumeController::VolumeController(QWidget *parent) :
      QWidget(parent),
      ui(new Ui::VolumeController) {
      ui->setupUi(this);
    
      ui->volume->setSliderPosition(VOLUME.get());
      connect(ui->volume, SIGNAL(sliderMoved(int)), &VOLUME, SLOT(set(int)));
      connect(&VOLUME, SIGNAL(changed(int)), ui->volume, SLOT(setValue(int)));
    }
    
    VolumeController::~VolumeController() {
      delete ui;
    }

    Чтобы проверить как это работает, я добавил в файл ресурсов файл с песней, подключил к проекту multimedia (QT += multimedia) и добавил следующий код в main.cpp:

    #include "volumecontroller.h"
    #include <QApplication>
    #include <QMediaPlayer>
    #include "settings_db/volume.h"
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
    
        VolumeController controller;
        controller.show();
    
        QMediaPlayer player;
        QObject::connect(&VOLUME, SIGNAL(changed(int)), &player, SLOT(setVolume(int)));
    
        player.setMedia(QUrl("qrc:/sounds/resources/sound.ogg"));
        player.setVolume(VOLUME.get());
        player.play();
    
        return a.exec();
    }

    В данном случае отображается виджет VolumeController, а также создается объект класса QMediaPlayer, способного проигрывать звук. Выставляется начальное значение громкости в соответствии с параметрами, сохраненными в базе данных и выполняется соединение сигнала изменения громкости со слотом проигрывателя. Полный код примера можно взять в репозитории (ссылка в конце статьи).

    Виджет-кнопка

    Во многих случаях описанный выше виджет не подойдет, т.к. он занимает достаточно много места на экране. Например, если вы разрабатываете игрушку и в ней есть звук — то неплохо бы разместить на всех экранах приложения кнопку его выключения (если в вашу игру будут играть школьники на переменах — им такая кнопка однозначно поможет). Такой виджет является обычной кнопкой, поэтому мы наследуем QPushButton:

    #include <QPushButton>
    
    class VolumeTumbler : public QPushButton {
      Q_OBJECT
    public:
      explicit VolumeTumbler(QWidget *parent = 0);
    signals:
      void setVolume(int);
    private slots:
      void on_volumeChanged(int);
      void on_buttonPressed();
    private:
      void updateIcon();
      enum class State { On, Off } m_state;
    };

    При нажатии на кнопку (слот on_buttonPressed) вырабатывается сигнал setVolume и изменяется пиктограмма на кнопке. Звук может быть изменен и с помощью регулятора, если звук был включен, но затем с помощью регулятора (описанного выше) была выставлена громкость равная нулю — то пиктограмма также должна измениться. Если звук был отключен, но затем регулятором было выставлено значение громкости отличное от нуля — пиктограмма на кнопке опять изменяется. Для этого класс должен обрабатывать изменение громкости (слот on_volumeChanged).

    В конструкторе класса выполняется соединение объекта с сигналами и слотами VOLUME:
    #include «volumetumbler.h», а также выставляется начальная пиктограмма кнопки:
    #include «settings_db/volume.h»

    VolumeTumbler::VolumeTumbler(QWidget *parent) : QPushButton(parent) {
      on_volumeChanged(VOLUME.get());
      connect(this, SIGNAL(setVolume(int)), &VOLUME, SLOT(set(int)));
      connect(&VOLUME, SIGNAL(changed(int)), this, SLOT(on_volumeChanged(int)));
      connect(this, SIGNAL(pressed()), SLOT(on_buttonPressed()));
    }

    При нажатии на кнопку изменяется состояние объекта, вызывается функция изменения иконки и вырабатывается сигнал изменения громкости:

    void VolumeTumbler::on_buttonPressed() {
      if (State::Off == m_state)
        m_state = State::On;
      else
        m_state = State::Off;
      updateIcon();
      emit setVolume(m_state == State::On ? 100 : 0);
    }

    Если изменена громкость — виджету выставляется состояние в зависимости от того, равна она нулю или нет, затем вызывается функция обновления иконки:

    void VolumeTumbler::on_volumeChanged(int value) {
      if (value == 0)
        m_state = State::Off;
      else
        m_state = State::On;
      updateIcon();
    }

    При обновлении иконок выставляется пиктограмма в соответствии с состоянием объекта:

    void VolumeTumbler::updateIcon() {
      if (State::Off == m_state)
        setIcon(QIcon(":/images/resources/volume_off.svg"));
      else
        setIcon(QIcon(":/images/resources/volume_on.svg"));
    }

    Оба примера, описанных в статье можно посмотреть в репозитории.

Для ответа в этой теме необходимо авторизоваться.