Шаг 240.
Библиотека Qt.
Машина состояний и переходы

    На этом шаге рассмотрим машину состояний в Qt.

    Цель состояний (States) заключается в создании различных аспектов приложения. С их помощью можно присвоить различные значения свойствам объектов, которые будут храниться в определенном объекте состояния. Таким образом можно создать много состояний и поместить их в группу состояний. Логика функционирования этой группы подобна использованию кнопок переключения, т. е. активным может быть только одно состояние и активация одного из состояний деактивирует все остальные. Если мы будем показывать одно состояние, затем другое, третье и т. д., то просто одна картинка будет резко сменяться другой и получится что-то похожее на показ слайдов, а это не так уж и привлекательно. Поэтому между отдельными состояниями нужны более плавные переходы (Transitions). Переходы являются инструментом смены состояний и соединения состояний с анимациями. В качестве демонстрации работы состояний и переходов реализуем пример элемента базирующегося на двух состояниях Off/On. Первое состояние Off является начальным. Нажатие на кнопку Push будет перемещать ее в противоположный конец и изменять текущее состояние, как это показано на рис. 1.


Рис.1. Состояния и переходы

QWidget wgt;//создаем виджет, на поверхности которого будем размещать элементы
wgt.setFixedSize(300, 50);//задаем ему постоянные размеры
wgt.show();
QLabel* plblOff = new QLabel("Off");//создаем виджеты надписей
QLabel* plblOn = new QLabel("On");
QHBoxLayout* phbx = new QHBoxLayout;//размещаем их в менеджере компоновки
phbx->addWidget(plblOn);
phbx->addStretch(1);
phbx->addWidget(plblOff);
wgt.setLayout(phbx);
QPushButton* pcmd = new QPushButton("Push", &wgt);//создаем виджет кнопки
pcmd->setAutoFillBackground(true);
pcmd->show();
int nButtonWidth = wgt.width() / 2;
QStateMachine* psm = new QStateMachine;/*создаем объект машины состояний,
                                         которая будет управлять нашими состояниями*/
QState* pStateOff = new QState(psm);//создаем первое состояние для состояния Off
QRect rect1(0, 0, nButtonWidth, wgt.height());
pStateOff->assignProperty(pcmd, "geometry", rect1);/*устанавливаем значение
                                                     геометрии для кнопки*/
pStateOff->assignProperty(plblOff, "visible", true);/*устанавливаем состояния
                                                      видимости для текстовых
                                                      надписей. В состоянии Off
                                                      текстовая надпись Off должна
                                                      быть видима, а On нет*/
pStateOff->assignProperty(plblOn, "visible", false);
psm->setInitialState(pStateOff);/*вызов этого метода c передачей указателя pStateOff,
                                  из объекта машины состояний делает это состояние
                                  начальным*/
QState* pStateOn = new QState(psm);/*для состояния On так же вызываем серию методов
                                     assignProperty(), только присваиваем другие
                                     значения, соответствующие этому состоянию*/
QRect rect2(nButtonWidth, 0, nButtonWidth, wgt.height());
pStateOn->assignProperty(pcmd, "geometry", rect2);
pStateOn->assignProperty(plblOff, "visible", false);
pStateOn->assignProperty(plblOn, "visible", true);
QSignalTransition* ptrans1 =
pStateOff->addTransition(pcmd, SIGNAL(clicked()), pStateOn);/*добавляем переход из
                                                              того состояния, из
                                                              которого вызван этот
                                                              метод, в другое,
                                                              указанное в этом методе
                                                              третьим параметром
                                                              состояния, мы хотим
                                                              перейти из состояния
                                                              Off в состояние On,
                                                              первым и вторым пара-
                                                              метром мы указываем,
                                                              что этот переход должен
                                                              происходить при нажатии
                                                              на кнопку Push*/
QSignalTransition* ptrans2 =
pStateOn->addTransition(pcmd, SIGNAL(clicked()), pStateOff);/*аналогично поступаем
                                                 и с состоянием On, но только в
                                                 обратном порядке.
                                                 Метод addTransction() возвращает
                                                 указатель на объект класса
                                                 QSignalTransition, который мы
                                                 используем дальше для присвоения
                                                 переходу нужной анимации*/
QPropertyAnimation* panim1 =
new QPropertyAnimation(pcmd, "geometry");/*создаем две анимации (указатели panim1 и
                                           panim2) для перехода в состояние On и Off
                                           и устанавливаем их вызовом методов
                                           addAnimation() в объектах переходов
                                           (указатели ptrans1 и ptrans2)*/
ptrans1->addAnimation(panim1);
QPropertyAnimation* panim2 =
new QPropertyAnimation(pcmd, "geometry");
ptrans2->addAnimation(panim2);
psm->start();//выполним запуск созданной нами машины состояний вызовом слота start()

    Файлы приложения можно взять здесь.

    На следующем шаге рассмотрим основные положения OpenGL.




Предыдущий шаг Содержание Следующий шаг