2017-01-31 2 views
2

Я пытаюсь создать систему, которая организована основным автоматом и имеет разные машины подсетей для выполняемых задач. Будучи долговременным пользователем Qt, я рассмотрел новую реализацию SCXML в Qt 5.8. Однако я не могу понять, как использовать API, предоставляемый с 5.8, для правильного использования подчиненных машин.Qt 5.8 Как использовать инфраструктуру SCXML с подзаголовками?

Моя идея состоит в том, чтобы использовать главный государственный аппарат, а затем вызывать специальные машины подзаголовка в состояниях основного конечного автомата. При вызове работы подгосударственных машин я не мог понять, как получить доступ к ним после того, как высшие объекты конечного автомата испускают invokedServicesChanged(..). Я могу получить доступ к указателю на QScxmlInvokableService, но не в отношении конечного автомата.

Также объект состояния государственного уровня верхнего уровня раскрывает состояния и события сверху, а не из вызываемых состояний машин. Например, topLevelStateMachine->activeStateNames() перечисляет только верхние состояния.

Глядя на исходный код Qt, я увидел, что QScxmlInvokableService на самом деле является базовым классом для QScxmlScxmlService, который содержит указатель на соответствующий конечный автомат. К сожалению, QScxmlScxmlService определен в qscxmlinvokableservice_p.h, который является закрытым, так как обозначение _p. Итак, как я должен использовать открытый SCXML API? Я что-то упускаю? Поддержка IIRC SCXML была техническим предварительным просмотром в 5.7, но теперь включена в 5.8 как часть нормального распределения.

+1

Я бы сказал, что это надзор в API. Не стесняйтесь добавлять в проект 'QT + = scxml_private' и использовать детали реализации, чтобы сделать то, что вам нужно. Этот модуль Qt является совершенно новым и да, ему не хватает довольно много необходимых бит, чтобы сделать его полезным. –

+0

Когда вы говорите «машины вспомогательных состояний», ссылаетесь ли вы на отдельные конечные машины '.scxml' или ссылаетесь на [составные состояния] (https://www.w3.org/TR/scxml/#N10192)? Если первое, то почему не последнее? – Phrogz

+0

Отдельные государственные машины. Я не думаю, что наличие большой конечной машины в одном XML-файле является хорошей идеей, но теоретически она также может быть решена с помощью составных состояний. Как бы вы организовали диаграмму с большим количеством состояний, используя SCXML и Qt? – Nils

ответ

0

Я провел последнюю неделю или около того, изучая примеры, а затем написал свой собственный автомат и код, который отвечает на него. Потребовалось некоторое время, поскольку документация не так ясна, как могла бы быть.

Я обнаружил, что activeStateNames действительно извлекает все состояния, содержащиеся в конечной машине, включая под-состояния.

Мне понадобилось пару показаний traffic light example, чтобы понять это. Ключ состоит в том, что машины под-состояния содержатся в определенных состояниях. (Графический вид конечного автомата помогает здесь.)

В примере на машине общего уровня всего верхнего уровня находятся только два состояния: working и broken. Переходы контролируются событиями smash и repair.

В каждом из двух состояний используются миниатюрные автоматы. Сломанный содержит машину состояний двух состояний: blinking и unblinking. Этот конечный автомат начинается в состоянии blinking, когда вводится broken.

Когда в подсостояние blinking из broken, activeStateNames будет возвращать blinking, если вызывается с false (дефолт) или blinking и broken при вызове с true.

Итак, как вы это используете?

Если у меня есть что-то, что я хочу установить/отключить в соответствии с конкретным состоянием, я могу connectToState в машине. Слот, к которому я подключаюсь, вызывается, когда состояние изменяется между активным и неактивным, и оно получает логическое значение, указывающее, активно ли состояние. В примере светофора состояние red подключено к redLight. Поскольку redLight должен быть включен, когда в состоянии red, а не в другом месте, он подключен к слоту, принимает логическое значение: true включает свет, false отключает его.

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

Я просто выбираю состояние, а затем добавляю onEntry -> send и указываю имя события. Это приведет к отправке события при входе в состояние. Это событие можно перенаправить в слот (в Qt 5.8) с использованием connectToEvent. [Версия Qt 5.7 имеет только общий сигнал eventOccurred, который вы можете отправить в слот, а затем запросить, какое событие использует event.name().

Смежные вопросы