»спользование pyatspi2 дл€ исследовани€ графических пользовательских интерфейсов

ƒата публикации:06.04.2023
ѕоделитьс€ в Twitter ѕоделитьс€ в F******k ѕоделитьс€ в VKontakte ѕоделитьс€ в Telegram

ќсновой дл€ статьи послужил материал PyAtSpi2Example.

¬ведение

—пецификаци€ AT-SPI представл€ет собой набор протоколов и соглашений о взаимодействии операционной системы, прикладных программ и вспомогательных технологий с целью обеспечить доступ к графическому пользовательскому интерфейсу дл€ лиц с различными ограничени€ми здоровь€, нарушающими работу органов чувств, когнитивные функции и / или координацию движений. AT-SPI примен€етс€ в графических пользовательских окружени€х дистрибутивов GNU/Linux и стандартизована в группе стандартов ISO/IEC 13066.

ƒл€ того чтобы изучить, как элементы пользовательского интерфейса представлены средствами AT-SPI дл€ вспомогательных технологий, подойдЄт модуль pyatspi, содержащий прив€зки AT-SPI дл€ python. “акже pyatspi будет полезен дл€ создани€ автоматизированных тестов доступности пользовательского интерфейса приложени€ и дл€ проверки работоспособности пользовательского интерфейса приложени€ в целом. —тоит отметить, что во операционных системах инфраструктура поддержки вспомогательных технологий часто совмещена со средствами автоматического тестировани€ пользовательского интерфейса, поскольку обе задачи базируютс€ на машиночитаемой информации, которую о своЄм интерфейсе предоставл€ет приложение и которую затем пожно использовать либо дл€ проверки работоспособности виджетов (например, инструмент Accerciser), либа дл€ представлени€ его пользователю невизуальным способом (например, программа экранного доступа Orca, использующа€ синтез речи и тактильный вывод).

¬ пакетных базах многих дистрибутивов GNU/Linux уже имеютс€ готовые сборки pyatspi. Ќапример, в Ubuntu pyatspi можно установить командой с правами root:

apt install python-pyatspi

»сследование дерева AT-SPI

¬ системах графического пользовательского интерфейса элементы, как правило, организованы в виде иерархического дерева со св€з€ми родитель (контейнер) Ч потомки, которые сами могут быть контейнерными элементами дл€ потомков следующего уровн€, а могут и не содержать дочерних элементов. ѕо этой причине представление пользовательского интерфейса дл€ целей вспомогательных технологий (assistive technology) выполн€етс€ в виде иерархического дерева, которое часто называют деревом доступности (accessibility three). —пецификаци€ AT-SPI не €вл€етс€ исключением и экспонирует элементы управлени€ (виджеты) пользовательского интерфейса в виде иерархического дерева AT-SPI, навигацию по которому можно осуществл€ть, использу€ API модул€ pyatspi.

 онечно, сначала нужно импортировать пространство имЄн модул€ pyatspi:

import pyatspi

«атем можно перечислить активные приложени€:

desktop = pyatspi.Registry.getDesktop(0)
for application in desktop:
print(application.name)

“еперь посмотрим, чтчто представл€ет собой приложение в смысле пользовательского интерфейса:

a = desktop[0]
print(a.name)
for o in a:
print(o)

ѕример вывода (зависит от того, какие приложени€ открыты во врем€ выполнени€ кода):

gucharmap
[frame | Character Map]

—ледовательно, это приложение gucharmap, которое имеет одно окно (фрейм), с заголовком ЂCharacter Mapї. Ётот объект, как и остальные элементы дерева AT-SPI, позвол€ет взаимодействовать с объектами доступности (accessibility object).

»так, что можно получить:

for o in a:
print(o.role, o.name)

¬ывод:


 Character Map

Ёто значени€ свойств объекта доступности, св€занного с окном приложени€ (фреймом) Ч роль и наименование.

“еперь ѕерейдЄм на один уровень глубже:

frame = a[0]
for o in frame:
print(o)

¬ывод:

[panel | ]
[menu bar | ]

—ледовательно, фрейм содержит панель и строку меню.

“еперь покажем содержимое панели:

panel = frame[0]
for o in panel:
print(o)

¬ывод:

[status bar | U+10000 LINEAR B SYLLABLE B008 A]
[text | test]
[push button | Copy]
[label | Text to copy:]
[split pane | ]
[filler | Font]

ѕанель содержит, помимо прочего, поле дл€ ввода текста и метку. ” них разные роли, но эти объекты реализуют интерфейс дл€ получени€ текстового содержимого, что позвол€ет манипулировать этим содержимым:

t = panel[1]
l = panel[3]
print(t.role)
print(l.role)
t_text = t.queryText()
l_text = l.queryText()

ѕодробнее о взаимодействии с текстовым содержимым объектов доступности см.: pydoc pyatspi.Text

print(t_text.caretOffset)
print(l_text.caretOffset)

ќбратите внимание, что .name виджета может не отличатьс€, а может отличатьс€ от его содержимого: например, пол€ дл€ ввода текста обычно имеют метку, котора€ сообщает, дл€ чего предназначена текстовое поле, так что .name будет содержать текст метки, а текстовое поле будет содержать введЄнный текст.

ќт дочернего узла можно вернутьс€ к родительскому:

p = t.parent
print(p == panel)

ƒл€ того чтобы отслеживать изменени€, происход€щие с элементами дерева AT-SPI, рассмотрим, как реагировать на событи€...

–еакци€ на событи€

—обыти€ AT-SPI Ч это способ уведомить вспомогательные технологии об изменени€х, которые произошли в пользовательском интерфейсе приложени€. “акие изменени€ могут быть вызваны действи€ми пользовател€ (активаци€ элементов, перемещение фокуса, ввод текста и т.д.) или самим приложением (всплывающие уведомлени€, сообщени€ в строке статуса и т.д.).

Ќапример, чтобы следить за перемещением текстового курсора (каретки), необходимо зарегистрировать обработчик соответствующего событи€:

def f(e):
print(e.source, " got caret ", e.detail1)
pyatspi.Registry.registerEventListener(f, "object:text-caret-moved")
pyatspi.Registry.start()

¬ывод после некоторых действий пользовател€:

[text | ] got caret 2
[text | ] got caret 1
[text | ] got caret 0
[entry | ] got caret 23
[entry | ] got caret 24
[entry | ] got caret 25

Ётот вывод показывает, что пользователь переместил курсор внутри текстового виджета, а затем в виджет записи.

—хожим образом можно отслеживать перемещение фокуса:

def f(e):
print(e.source, " got focus " if e.detail1 else " lost focus")
pyatspi.Registry.registerEventListener(f, "object:state-changed:focused")
pyatspi.Registry.start()

и это позволит получить интересный вывод дл€ последующей обработки.

ћожно отслеживать все варианты изменени€ состо€ни€, зарегистрировав обработчики дл€ object:state-changed и т.д. —писок событий можно узнать из XML-спецификации базового протокола dbus: https://github.com/GNOME/at-spi2-core/blob/master/xml/Event.xml. Ќапример, событие xml Object StateChanged dbus соответствует строке "object:state-changed" при регистрации обработчика в pyatspi2.

—сылки



–аспространение материалов сайта означает, что распространитель прин€л услови€ лицензионного соглашени€.
»де€ и реализаци€: © ¬ладимир ƒовыденков и јнатолий  амынин,  2004-2023