Интерфейс

Создание кнопок

Расположение кнопки в интерфейсе ГИС «Аксиома» определяется Вкладкой и Группой. Например, вкладка “Основные” группа “Команды”. В модуле axipy.menubar` есть необходимые функции для создания кнопок.

button = ActionButton('Простое действие', on_click=lambda: print('triggered'))
position = Position('Основные', 'Команды')
position.add(button)

Детально разберем, что делает этот пример.

Создается кнопка с текстом “Простое действие”, и ,используя параметр on_click, привязывается нажатие на кнопку к анонимной лямбде, которая печатает в консоль текст «triggered». Это обработчик нажатия кнопки. Обработчиком может служить любой callable-объект(функтор) без параметров, т.е. функции, лямбды, объекты с методом __call__. Также можно задать иконку кнопки параметром icon=. Иконкой может быть строка-ссылка на ресурс или объект типа PySide2.QtGui.QIcon.

Далее ищется расположение в интерфейсе. Если вкладка или группа с такими именами отсутствуют, то они будут созданы при добавлении кнопки.

В последней строке кнопка добавляется в заданное расположение.

Передача параметров в инструменты

Дополнительные параметры могут быть переданы прямо в конструктор инструмента axipy.gui.MapTool при создании кнопки axipy.menubar.ToolButton. Для этого необходимо «обернуть» вызов конструктора в функцию, захватив (capture) все необходимые параметры. Например, сравните:

Инструмент без параметров
button = ToolButton('Мой инструмент', MyTool)
Инструмент с захватом параметров
button = ToolButton('Мой инструмент', lambda: MyTool(config, params))

Наблюдатели значений

В приложении ГИС «Аксиома» многие кнопки и инструменты меняют свойство доступности в зависимости от текущего состояния. Например, если кнопка производит действие над выбранным объектом, то логично сделать эту кнопку доступной только при наличии выбранных объектов. Чтобы проще задавать подобное поведение для своих кнопок, предлагается использовать axipy.da.ValueObserver и место их регистрации axipy.da.state_manager.

Так, чтобы сделать кнопку активной только при наличии выборки, ее можно создать следующим образом, передав параметр enable_on функции axipy.menubar.create_button():

button = menubar.create_button('Имя кнопки', on_click=action_func,
        enable_on=state_manager.Selection)

Идентификаторы наблюдателей по умолчанию перечислены в axipy.da.DefaultKeys; они также доступны в axipy.da.state_manager.

Для инструментов идентификатор рекомендуется задавать в самом классе инструмента, переопределив параметр axipy.gui.MapTool.enable_on.

Возможно добавление своих наблюдателей, в том числе их комбинация с уже существующими axipy.da.StateManager.create().

Примечание

  • Наблюдатели значений могут использоваться и для других целей.

  • Не все наблюдатели имеет смысл комбинировать друг с другом; некоторые значения являются взаимоисключающими.

  • Не все наблюдатели напрямую подходят для задания доступности кнопкам, а скорее лишь те, которые имеют тип bool. В общем случае наблюдение может быть за любыми базовыми значениями: int, str, list и прочее.

Чтобы просто получить текущее значение наблюдателя, используется метод axipy.da.ValueObserver.value().

Панель активного инструмента

Если при работе с инструментом пользователю регулярно нужно взаимодействовать с различными графическими элементами / настройками то для этого можно воспользоваться готовым решением из ActiveToolPanel. Это обертка вокруг стандартной панели QDockWidget предоставляющая дополнительные возможности:

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

  2. Предопределенное место для панели активного инструмента.

  3. Готовые компоненты с кнопками управления для упрощения добавления пользовательского графического элемента.

При написании плагинов текущий экземпляр ActiveToolPanel можно получить из метода axipy.AxiomaInterface.active_tool_panel(). Взаимодействие с панелью активного инструмента идет через обработчик который можно создать через один из методов make_acceptable() или make_custom(). При работе с панелью активного инструмента через обработчик AxipyAcceptableActiveToolHandler созданный через make_acceptable() то на панели активного инструмента по умолчанию расположены кнопки «Применить» и «Отмена». При нажатии на них будут посланы соответствующие сигналы accepted и rejected. Если нужно настроить кнопки управления по своему усмотрению то можно воспользоваться обработчиком AxipyCustomActiveToolPanelHandler, который создаётся с помощью make_custom().

Создание обработчика для взаимодействия с панелью активного инструмента.
service = ActiveToolPanel()
# Любой пользовательский графический элемент
widget = QWidget()

# Создаём обработчик для панели активного инструмента через который 
# будем управлять панелью. 
tool_panel = service.make_acceptable(
    title="Мой инструмент",
    observer_id=DefaultKeys.SelectionEditable,
    widget=widget)

# Подписываемся на сигнал отправляемый после нажатия на кнопку "Применить" в панели
tool_panel.accepted.connect(lambda: print("Применяем изменения"))

Чтобы показать панель активного инструмента с переданным ранее графическим элементом нужно вызвать activate(), а для закрытия deactivate().

Включение/Выключение панели активного инструмента.
class PyTool(MapTool):

    def mousePressEvent(self, event: QMouseEvent) -> Optional[bool]:
        if event.button() == Qt.LeftButton:
            self.tool_panel.activate()
        return self.PassEvent

    def keyPressEvent(self, event: QKeyEvent) -> Optional[bool]:
        if event.key() == Qt.Key_Escape:
            self.tool_panel.deactivate()
            return self.BlockEvent
        return super().keyPressEvent(event

См.также

Создание и добавление кнопок Создание кнопок

В коде выше в методе mousePressEvent() при нажатии левой кнопкой мыши мы показываем панель с активным инструментом, а в методе keyPressEvent() при нажатии на клавишу Esc панель закрываем.

Окно редактирования карты

Окно карты axipy.render.Map, созданное программно, можно экспортировать в виде растра или же поместить в отчет. Если же стоит задача проведения некоторых манипуляций с картой, таких как редактирование геометрии, то для проведения подобных манипуляций ее необходимо поместить в окно редактирования axipy.gui.MapView. Для создания этого окна необходимо использовать метод axipy.gui.ViewManager.create_mapview(). Данный метод доступен через сервис view_manager. Рассмотрим на примере:

Пример использования.
# Откроем таблицу, создадим на ее базе слой и добавим в карту
table_world = provider_manager.openfile(filepath)
world = Layer.create(table_world)
map = Map([ world ])
# Для полученной карты создадим окно просмотра
mapview = view_manager.create_mapview(map)

Окно легенды для карты

Для просмотра и редактирования легенды axipy.render.Legend для карты необходимо использовать метод axipy.gui.ViewManager.create_legendview(), передав в него как параметр окно ранее созданной карты:

Пример использования.
map = Map([ world ])
mapview = view_manager.create_mapview(map)
legendView = view_manager.create_legendview(mapview)

При этом будут помещены все доступные для просмотра легенды слоев карты map_view.

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

Пример использования.
for legend in legendView.legends:
   print(legend.caption)
'''
>>> World
'''

Окно редактирования отчета

Если необходимости в визуальном редактировании отчета axipy.render.Report нет, а требуется только программно создать макет отчета и распечатать его на принтере или сохранить как PDF, то достаточно создать axipy.render.Report и работать с ним. В противном случае отчет, по аналогии с картой для визуального редактирования его так же помещают в окно редактирования axipy.gui.ReportView. В качестве примера создадим окно отчета и поместим в него геометрию и карту. Стоит заметить, что карту так-же можно использовать у уже открытого окна карты axipy.gui.MapView.map(). Координаты элементов задаются в единицах измерения отчета axipy.render.Report.unit. В нашем случае это миллиметры.

Пример использования.
from PySide2.QtCore import Qt
rv = view_manager.create_reportview()

# Добавим полигон
geomItem = GeometryReportItem()
geomItem.geometry = Polygon((10,10), (10, 100), (100, 100), (10, 10))
geomItem.style = PolygonStyle(45, Qt.red)
rv.report.items.add(geomItem)

# Добавим направляющую
rv.x_guidelines.append(20)

# Текущий масштаб просмотра
rv.scale = 33

# Включение режима привязки координат
rv.snap_mode = True

# Размер ячейки сетки
rv.mesh_size = 20

# Откроем и добавим карту
table = provider_manager.openfile(filepath)
world = Layer.create(table)
map = Map([ world ])
mapItem = MapReportItem(Rect(10, 100, 200, 200), map)
mapItem.scale = 200000000
rv.report.items.add(mapItem)

# Поменяем стиль у первого объекта
rv.report.items[0].style = PolygonStyle(45, Qt.blue)