Skip to content

Latest commit

 

History

History
245 lines (177 loc) · 13.5 KB

File metadata and controls

245 lines (177 loc) · 13.5 KB
Открытие экранов

Экран может быть открыт из главного меню, навигацией к URL, или программно из другого экрана. В данном разделе мы рассмотрим, как открывать экраны программно.



Интерфейс Screens

Интерфейс Screens позволяет создавать и отображать экраны всех типов.

Предположим, у нас есть экран для демонстрации сообщения с особым форматированием:

Контроллер экрана
link:../../../../../source/gui/screens/screens_1.java[role=include]
  1. - параметр экрана

XML-дескриптор экрана
link:../../../../../source/gui/screens/screens_1.xml[role=include]

В этом случае мы можем создать и открыть его из другого экрана следующим образом:

link:../../../../../source/gui/screens/screens_2.java[role=include]

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

Если экран не требует передачи параметров из вызывающего кода, его можно создать и открыть одной строкой:

link:../../../../../source/gui/screens/screens_3.java[role=include]
Warning

Screens не является Spring-бином, поэтому его можно только инжектировать в контроллер экрана или получить его с помощью статического метода ComponentsHelper.getScreenContext(component).getScreens().

Бин ScreenBuilders

Бин ScreenBuilders позволяет открывать все типы экранов с различными параметрами. Ниже приведён пример вызова экрана и выполнения некоторого кода после того, как экран закрывается (более подробно см. здесь):

link:../../../../../source/gui/screens/screenBuilders_withAfterCloseListener.java[role=include]

Далее мы рассмотрим работу с экранами редактирования и выбора сущностей.

Пример открытия редактора по умолчанию для сущности Customer:

link:../../../../../source/gui/screens/screenBuilders_editor.java[role=include]

В данном примере редактор изменит экземпляр сущности Customer, но вызывающий экран не получит назад обновлённую сущность.

Часто требуется отредактировать сущность, отображаемую, к примеру, компонентом Table или DataGrid. В этом случае следует использовать другую форму вызова редактора, она короче и позволяет автоматически обновить исходный экземпляр в таблице:

link:../../../../../source/gui/screens/screenBuilders_editor_2.java[role=include]

Чтобы создать новый экземпляр сущности и открыть экран его редактирования, достаточно вызвать метод newEntity() builder’а:

link:../../../../../source/gui/screens/screenBuilders_editor_3.java[role=include]
Tip

Редактор сущности по умолчанию определяется по следующей схеме:

  1. Если существует экран редактирования с аннотацией @PrimaryEditorScreen, будет использован он.

  2. Если такого экрана нет, будет использован экран с идентификатором вида {entity_name}.edit (например, sales_Customer.edit).

Builder предоставляет множество методов для передачи дополнительных параметров в открываемый экран. К примеру, следующий код создаёт сущность, сначала инициализируя новый экземпляр, в конкретном экране редактирования, открываемом в режиме диалогового окна:

link:../../../../../source/gui/screens/screenBuilders_editor_4.java[role=include]

Экраны выбора сущностей также можно открывать с различными параметрами.

Пример открытия экрана выбора по умолчанию для сущности User:

link:../../../../../source/gui/screens/screenBuilders_lookup.java[role=include]

Если нужно установить выбранную сущность в качестве значения поля, используйте краткую форму вызова:

link:../../../../../source/gui/screens/screenBuilders_lookup_2.java[role=include]
Tip

Экран выбора сущности по умолчанию определяется по следующей схеме:

  1. Если существует экран выбора с аннотацией @PrimaryLookupScreen, будет использован он.

  2. Если такого экрана нет, будет использован экран с идентификатором вида {entity_name}.lookup (например, sales_Customer.lookup).

  3. Если и такого экрана нет, будет использован экран с идентификатором вида {entity_name}.browse (например, sales_Customer.browse).

Как и в случае с экранами редактирования, вы можете использовать методы builder’а для передачи дополнительных параметров в открываемые экраны. Например, следующий код поможет выбрать сущность User в конкретном экране выбора, открываемом в режиме диалогового окна:

link:../../../../../source/gui/screens/screenBuilders_lookup_3.java[role=include]
Передача параметров в экраны

Рекомендуемый способ передачи параметров в открываемый экран - использование публичных setter-методов контроллера, как продемонстрировано в примере выше.

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

link:../../../../../source/gui/screens/passing_parameters_1.java[role=include]

Другой способ - определить специальный класс для параметров и передавать экземпляр этого класса в стандартный метод withOptions() билдера. Класс параметров должен реализовывать маркер-интерфейс ScreenOptions. Например:

link:../../../../../source/gui/screens/passing_options_1.java[role=include]

В открываемом экране FancyMessageScreen, объект параметров может быть получен в обработчиках InitEvent и AfterInitEvent:

link:../../../../../source/gui/screens/passing_options_2.java[role=include]

Пример вызова экрана FancyMessageScreen через ScreenBuilders с передачей ScreenOptions:

link:../../../../../source/gui/screens/passing_options_3.java[role=include]

Как видите, данный подход требует приведения типов в контроллере, получающем параметры, поэтому используйте его только когда это необходимо и предпочитайте type-safe подход с setter-методами, описанный выше.

Использование объекта ScreenOptions является единственным способом получения параметров, если экран открывается из другого экрана, основанного на устаревшем API. В этом случае, объект параметров имеет тип MapScreenOptions и может быть обработан следующим образом:

link:../../../../../source/gui/screens/passing_options_4.java[role=include]
Выполнение кода после закрытия и возврат значений

Каждый экран посылает событие AfterCloseEvent после своего закрытия. Экрану можно добавить слушатель для нотификации об этом событии, например:

link:../../../../../source/gui/screens/return_values_1.java[role=include]

При использовании ScreenBuilders, слушатель можно передать в методе withAfterCloseListener():

link:../../../../../source/gui/screens/return_values_2.java[role=include]

Объект события предоставляет информацию о том, как экран был закрыт: его метод getCloseAction() возвращает объект с интерфейсом CloseAction. Интерфейс FrameOwner, реализуемый контроллерами экранов, содержит несколько констант, определяющих реализации CloseAction, используемые фреймворком. В приложении можно использовать эти константы, либо определить свои собственные реализации.

Рассмотрим следующий простой экран:

link:../../../../../source/gui/screens/return_values_3.java[role=include]
  1. - при нажатии кнопки "OK", установить некоторое результирующее значение и закрыть экран со стандартным действием закрытия WINDOW_COMMIT_AND_CLOSE_ACTION.

  2. - при нажатии кнопки "Cancel", закрыть экран с действием закрытия по умолчанию.

Теперь в слушателе AfterCloseEvent можно проанализировать, как экран был закрыт, и, если необходимо, прочитать возвращаемое экраном значение:

link:../../../../../source/gui/screens/return_values_4.java[role=include]

Другим способом возврата значений из экранов является использование собственных реализаций CloseAction. Перепишем пример, приведенный выше, с использованием следующего класса действия закрытия:

link:../../../../../source/gui/screens/return_values_5.java[role=include]

Теперь можно использовать данное действие при закрытии экрана:

link:../../../../../source/gui/screens/return_values_6.java[role=include]

Как видно из примера кода, при возврате значений через собственный CloseAction, вызывающий код не обязан знать класс открываемого экрана, так как ему не нужено вызывать его методы. По тому экран можно создавать по его строковому идентификатору.

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