1. Что такое GladeVCP?

GladeVCP — это компонент LinuxCNC, который добавляет возможность добавлять новую панель пользовательского интерфейса к пользовательским интерфейсам LinuxCNC, например:

  • AXIS

  • Touchy

  • Gscreen

  • GMOCCAPY

В отличие от PyVCP, GladeVCP не ограничивается отображением и настройкой контактов HAL, поскольку произвольные действия могут выполняться в коде Python — фактически, с помощью GladeVCP и Python можно создать полный пользовательский интерфейс LinuxCNC.

GladeVCP использует Glade редактор пользовательского интерфейса WYSIWYG, который позволяет легко создавать визуально привлекательные панели. Он опирается на привязки PyGObject к богатому набору виджетов GTK3, и фактически все эти виджеты может использоваться в приложении GladeVCP, а не только в специализированных виджетах для взаимодействия с HAL и LinuxCNC, которые описаны здесь.

1.1. Краткий обзор PyVCP и GladeVCP

Оба поддерживают создание панелей с HAL widgets — элементами пользовательского интерфейса, такими как светодиоды, кнопки, ползунки и т. д., значения которых связаны с контактом HAL, который, в свою очередь, взаимодействует с остальной частью LinuxCNC.

PyVCP:

  • Набор виджетов: использует виджеты TkInter.

  • Создание пользовательского интерфейса: цикл "редактировать XML-файл/выполнить результат/оценить внешний вид".

  • Нет поддержки внедрения пользовательской обработки событий.

  • Никакого взаимодействия LinuxCNC за пределами контактов ввода-вывода HAL не поддерживается.

GladeVCP:

  • Набор виджетов: зависит от набора виджетов GTK3.

  • Создание пользовательского интерфейса: используется Glade редактор пользовательского интерфейса WYSIWYG.

  • Любое изменение контакта HAL может быть направлено на обратный вызов определяемого пользователем обработчика событий Python.

  • Любой сигнал GTK (нажатие клавиши/кнопки, окно, ввод-вывод, таймер, сетевые события) может быть связан с определяемыми пользователем обработчиками в Python.

  • Прямое взаимодействие с LinuxCNC: выполнение произвольных команд, например, запуск команд MDI для вызова подпрограммы G-кода, а также поддержка операций изменения статуса с помощью виджетов действий.

  • Несколько независимых панелей GladeVCP можно запускать на разных вкладках.

  • Разделение внешнего вида и функциональности пользовательского интерфейса: меняйте внешний вид, не трогая код.

2. Краткий тур с примером панели

Окна панели GladeVCP можно запускать в трех различных конфигурациях:

  • всегда видимый интегрированный в AXIS с правой стороны, точно так же как панели PyVCP,

  • как вкладка в AXIS,Touchy, Gscreen или GMOCCAPY; в AXIS это создаст третью вкладку помимо вкладок Preview и DRO, которые необходимо вызвать явно,

  • как отдельное окно верхнего уровня, которое можно иконизировать/деиконифицировать независимо от главного окна.

Установленный LinuxCNC

Если вы используете установленную версию LinuxCNC, примеры, показанные ниже, находятся в configuration picker в ветке Sample Configurations > apps > GladeVCP.

Git Checkout

Следующие инструкции применимы только в том случае, если вы используете git checkout. Откройте терминал и перейдите в каталог, созданный git, затем введите команды, как показано.

Note
Чтобы следующие команды работали с вашей git checkout, вы должны сначала запустить make, затем sudo make setuid then run', а затем запустить . ./scripts/rip-environment. Дополнительную информацию о проверке git можно найти на вики-странице LinuxCNC.

Запустите образец панели GladeVCP, интегрированной в AXIS, например PyVCP, следующим образом:

$ cd configs/sim/axis/gladevcp
$ linuxcnc gladevcp_panel.ini
images/example-panel-small.png

Запустите ту же панель, но как вкладку внутри AXIS:

$ cd configs/sim/axis/gladevcp
$ linuxcnc gladevcp_tab.ini
images/example-tabbed-small.png

Чтобы запустить эту панель внутри Touchy:

$ cd configs/sim/touchy/gladevcp
$ linuxcnc gladevcp_touchy.ini
images/touchy-tab-33.png

Функционально эти настройки идентичны — они отличаются только требованиями к площади экрана и видимости. Поскольку можно запускать несколько компонентов GladeVCP параллельно (с разными именами компонентов HAL), возможны и смешанные настройки — например, панель с правой стороны и одна или несколько вкладок для менее часто используемых частей интерфейса.

2.1. Изучение примера панели

При запуске configs/sim/axis/gladevcp_panel.ini или configs/sim/axis/gladevcp_tab.ini изучите Show HAL Configuration — вы найдете компонент HAL gladevcp и сможете наблюдать значения их контактов при взаимодействии с виджетами в панель. Настройки HAL можно найти в файле configs/axis/gladevcp/manual-example.hal.

Панель примера имеет две рамки внизу. Панель настроена таким образом, что сброс ESTOP активирует рамку Settings, а включение машины активирует рамку Commands внизу. Виджеты HAL в рамке Settings связаны со светодиодами и метками в рамке Status, а также с текущим и подготовленным номером инструмента — поиграйте с ними, чтобы увидеть эффект. Выполнение команд T<toolnumber> и M6 в окне MDI изменит поля текущего и подготовленного номера инструмента.

Кнопки в рамке Commands представляют собой MDI Action widgets — нажатие на них приведет к выполнению команды MDI в интерпретаторе. Третья кнопка Execute Oword subroutine представляет собой расширенный пример — она берет несколько значений контактов HAL из поля Settings и передает их в качестве параметров в подпрограмму Oword. Фактические параметры, полученные подпрограммой, отображаются с помощью команд (DEBUG, ) — тело подпрограммы см. в ../../nc_files/oword.ngc.

Чтобы узнать, как панель интегрирована в AXIS, см. оператор [DISPLAY]GLADEVCP в configs/sim/axis/gladevcp/gladevcp_panel.ini, оператор [DISPLAY]EMBED* в configs/sim/axis/gladevcp/gladevcp_tab.ini и [HAL]POSTGUI_HALFILE как в configs/sim/axis/gladevcp/gladevcp_tab.ini, так и в configs/sim/axis/gladevcp/gladevcp_panel.ini.

2.2. Изучение описания пользовательского интерфейса

Пользовательский интерфейс создан с помощью редактора Glade UI — для его изучения вам необходимо его установить Glade installed. Чтобы отредактировать пользовательский интерфейс, выполните команду

$ glade configs/axis/gladevcp/manual-example.ui

Требуемая программа Glade может называться Glade-Gtk2 в более поздних системах.

В центральном окне показан внешний вид пользовательского интерфейса. Все объекты пользовательского интерфейса и объекты поддержки находятся в правом верхнем окне, где вы можете выбрать конкретный виджет (или кликнув на нем центральном окне). Свойства выбранного виджета отображаются и могут быть изменены в правом нижнем окне.

Чтобы увидеть, как команды MDI передаются из виджетов MDI Action, изучите виджеты, перечисленные в разделе Actions в правом верхнем углу окна, а в правом нижнем окне на вкладке General выберите свойство MDI command.

2.3. Изучение обратного вызова Python

Посмотрите, как обратный вызов Python интегрирован в пример:

  • В Glade см. виджет метки hits (простой виджет GTK+).

  • В виджете button1 перейдите на вкладку Signals и найдите сигнал pressed, связанный с обработчиком on_button_press.

  • В hitcounter.py посмотрите метод on_button_press и посмотрите, как он устанавливает свойство label в объекте hits.

Это лишь затрагивает концепцию — механизм обратного вызова будет рассмотрен более подробно в разделе GladeVCP Programming.

3. Создание и интеграция пользовательского интерфейса Glade

3.1. Обязательное условие: установка Glade

Для просмотра или изменения файлов пользовательского интерфейса Glade вам необходимо установить Glade 3.38.2 или более позднюю версию — она не нужна только для запуска панели GladeVCP. Если команда glade отсутствует, установите ее командой:

$ sudo apt install glade

Затем проверьте установленную версию, которая должна быть равна или выше 3.6.7:

$ glade --version

Glade содержит внутренний интерпретатор Python, поддерживается только Python 3. Это справедливо для Debian Bullseye, Ubuntu 21 и Mint 21 или более поздних версий. Старые версии не будут работать, вы получите ошибку Python.

3.2. Запуск Glade для создания нового пользовательского интерфейса

В этом разделе лишь описаны начальные шаги, специфичные для LinuxCNC. Дополнительную информацию и руководство по Glade можно найти на сайте http://glade.gnome.org. Некоторые советы и рекомендации Glade также можно найти на youtube.

Либо измените существующий компонент пользовательского интерфейса, запустив glade <file>.ui, либо запустите новый, просто запустив команду glade из оболочки.

  • Если LinuxCNC не был установлен из пакета, среду оболочки LinuxCNC необходимо настроить с помощью source <linuxcncdir>/scripts/rip-environment, иначе Glade не найдет виджеты, специфичные для LinuxCNC.

  • Когда вас спросят о несохраненных настройках, просто примите значения по умолчанию и нажмите Close.

  • В Toplevels (панель инструментов) выберите GtkWindow (первая запись) в качестве окна верхнего уровня. Установите window1 в качестве идентификатора на правой панели на вкладке General. Это именование важно, поскольку GladeVCP полагается на него.

  • С помощью кнопки с тремя точками вы можете найти виджеты, специфичные для LinuxCNC.

  • Добавьте в фрейм контейнер, например HAL_Box или HAL_Table из HAL Python.

  • Выберите и поместите некоторые элементы, такие как светодиод, кнопка и т. д., в контейнер.

Это будет выглядеть так:

images/glade-manual-small.png

Glade имеет тенденцию писать много сообщений в окно оболочки, которые в большинстве случаев можно игнорировать. Выберите File'→'Save as, дайте ему имя, например myui.ui, и убедитесь, что он сохранен как файл GtkBuilder (переключатель в левом нижнем углу диалогового окна «Save »). GladeVCP также корректно обрабатывает старый формат libglade, но использовать его нет смысла. Соглашение о расширении файла GtkBuilder — .ui.

3.3. Тестирование панели

Теперь вы готовы попробовать (пока работает LinuxCNC, например, AXIS) с помощью:

gladevcp myui.ui

GladeVCP создает компонент HAL, названный так же, как базовое имя файла пользовательского интерфейса - в данном случае myui - если он не переопределен опцией -c <component name>. Если вы используете AXIS, просто попробуйте Show HAL configuration и проверьте его контакты.

Вы можете задаться вопросом, почему виджеты, содержащие HAL_Hbox или HAL_Table, отображаются серым цветом (неактивными). Контейнеры HAL имеют связанный с ними контакт HAL, который по умолчанию отключен, что приводит к тому, что все содержащиеся в нем виджеты становятся неактивными. Обычным вариантом использования было бы связывание этих контактов HAL контейнера с сигналом halui.machine.is-on или одним из сигналов halui.mode, чтобы гарантировать, что некоторые виджеты будут активными только в определенном состоянии.

Чтобы просто активировать контейнер, выполните команду HAL setp Gladevcp.<имя-контейнера> 1.

3.4. Подготовка командного файла HAL

Предлагаемый способ связывания выводов HAL на панели GladeVCP — собрать их в отдельный файл с расширением .hal. Этот файл передается с помощью опции POSTGUI_HALFILE= в разделе HAL вашего INI-файла.

Caution
Не добавляйте командный файл GladeVCP HAL в раздел AXIS [HAL]HALFILE= ini, это не даст желаемого эффекта — см. следующие разделы.

3.5. Интеграция в AXIS, например PyVCP

Поместите панель GladeVCP на правую боковую панель, указав в INI-файле следующее:

[DISPLAY]
# add GladeVCP panel where PyVCP used to live:
GLADEVCP= -u ./hitcounter.py ./manual-example.ui

[HAL]
# HAL commands for GladeVCP components in a tab must be executed via POSTGUI_HALFILE
POSTGUI_HALFILE =  ./manual-example.hal

[RS274NGC]
# gladevcp Demo specific Oword subs live here
SUBROUTINE_PATH = ../../nc_files/gladevcp_lib

Имя компонента HAL по умолчанию для приложения GladeVCP, запускаемого с опцией GLADEVCP: gladevcp.

Командная строка, фактически запускаемая AXIS в приведенной выше конфигурации, выглядит следующим образом:

halcmd loadusr -Wn gladevcp gladevcp -c gladevcp -x {XID} -u ./hitcounter.py ./manual-example.ui

Вы можете добавить сюда произвольные параметры gladevcp, если они не конфликтуют с указанными выше параметрами командной строки.

Можно создать собственное имя компонента HAL, добавив параметр -c:

[DISPLAY]
# add GladeVCP panel where PyVCP used to live:
GLADEVCP= -c example -u ./hitcounter.py ./manual-example.ui

Командная строка, которую фактически запускает AXIS для вышеприведенного:

halcmd loadusr -Wn example gladevcp -c example -x {XID} -u ./hitcounter.py ./manual-example.ui
Note
Спецификаторы файлов, такие как ./hitcounter.py, ./manual-example.ui и т. д., указывают, что файлы расположены в том же каталоге, что и файл INI. Возможно, вам придется скопировать их в свой каталог (в качестве альтернативы укажите правильный абсолютный или относительный путь к файлу(ам)).
Note
Параметр [RS274NGC]SUBROUTINE_PATH= установлен только для того, чтобы панель примера нашла подпрограмму Oword (oword.ngc) для виджета MDI Command. Возможно, в вашей настройке это не понадобится. Спецификатор относительного пути ../../nc_files/gladevcp_lib создан для работы с каталогами, скопированными средством выбора конфигурации, а также при использовании установки запуска на месте.

3.6. Встраивание в виде вкладки

Для этого отредактируйте свой INI-файл и добавьте в разделы DISPLAY и HAL INI-файла следующим образом:

[DISPLAY]
# add GladeVCP panel as a tab next to Preview/DRO:
EMBED_TAB_NAME=GladeVCP demo
EMBED_TAB_COMMAND=halcmd loadusr -Wn gladevcp gladevcp -c gladevcp -x {XID} -u ./gladevcp/hitcounter.py ./gladevcp/manual-example.ui

[HAL]
# HAL commands for GladeVCP components in a tab must be executed via POSTGUI_HALFILE
POSTGUI_HALFILE =  ./gladevcp/manual-example.hal

[RS274NGC]
# gladevcp Demo specific Oword subs live here
SUBROUTINE_PATH = ../../nc_files/gladevcp_lib

Обратите внимание на способ запуска команды вкладки halcmd loadusr — это гарантирует, что POSTGUI_HALFILE будет запущен только после того, как компонент HAL будет готов. В редких случаях вы можете запустить здесь команду, которая использует вкладку, но не имеет связанного компонента HAL. Такую команду можно запустить без halcmd loadusr, и это означает для AXIS, что ей не нужно ждать компонента HAL, поскольку его нет.

При изменении имени компонента в приведенном выше примере обратите внимание, что имена, используемые в -Wn <component> и -c <component>, должны быть идентичными.

Попробуйте это, запустив AXIS — рядом с вкладкой DRO должна появиться новая вкладка под названием GladeVCP demo. Выберите эту вкладку, и вы увидите, что пример панели хорошо вписывается в AXIS.

Note
Убедитесь, что файл пользовательского интерфейса является последним параметром, передаваемым GladeVCP в операторах GLADEVCP= и EMBED_TAB_COMMAND=.

3.7. Интеграция в Touchy

Чтобы добавить вкладку GladeVCP в Touchy, отредактируйте свой INI-файл следующим образом:

[DISPLAY]
# add GladeVCP panel as a tab
EMBED_TAB_NAME=GladeVCP demo
EMBED_TAB_COMMAND=gladevcp -c gladevcp -x {XID} -u ./hitcounter.py -H ./gladevcp-touchy.hal  ./manual-example.ui

[RS274NGC]
# gladevcp Demo specific Oword subs live here
SUBROUTINE_PATH = ../../nc_files/gladevcp_lib
Note
Спецификаторы файлов, такие как ./hitcounter.py, ./manual-example.ui и т. д., указывают, что файлы расположены в том же каталоге, что и файл INI. Возможно, вам придется скопировать их в свой каталог (в качестве альтернативы укажите правильный абсолютный или относительный путь к файлу(ам)).

Обратите внимание на следующие отличия от настройки вкладки AXIS:

  • Командный файл HAL немного изменен, поскольку Touchy не использует компоненты halui, поэтому его сигналы недоступны, а некоторые ярлыки были использованы.

  • Параметр INI POSTGUI_HALFILE= отсутствует, но передача командного файла HAL в строке EMBED_TAB_COMMAND= допускается.

  • Заклинание halcmd loaduser -Wn … не требуется.

4. Параметры командной строки GladeVCP

См. также man gladevcp. Это параметры командной строки GladeVCP:

Использование: gladevcp [options] myfile.ui

Параметры:

-h, --help::
    Показывает это справочное сообщение и выходит.

-c NAME::
    Устанавливает имя компонента NAME. По умолчанию используется базовое имя файла пользовательского интерфейса.

-d::
    Разрешает вывод отладки

-g GEOMETRY::
     Настройте геометрию WIDTHxHEIGHT+XOFFSET+YOFFSET. Значения указаны в пикселях, XOFFSET/YOFFSET отсчет от верхнего левого угла экрана.
     Используйте -g WIDTHxHEIGHT для установки размера или -g +XOFFSET+YOFFSET для простого позиционирования.

-H FILE::
    Выполняет инструкции HAL из FILE с помощью halcmd после того, как компонент настроен и готов.

-m MAXIMUM::
    Принудительно развернуть окно панели.
    Вместе с опцией геометрии -g можно переместить панель на второй монитор и заставить ее использовать весь экран.

-t THEME::
    Устанавливает тему GTK. По умолчанию — системная тема. Разные панели могут иметь разные темы.

-x XID::
    Переназначает уровень GladeVCP в XID существующего окна вместо создания нового окна верхнего уровня.

-u FILE::
    Использовать файлы в качестве дополнительных пользовательских модулей с обработчиками.

-U USEROPT::
    передать USEROPT в модули Python

5. Понимание процесса запуска GladeVCP

Шаги интеграции, описанные выше, кажутся немного сложными, и это так. Таким образом, это помогает понять процесс запуска LinuxCNC и то, как он связан с GladeVCP.

Обычный процесс запуска LinuxCNC выполняет следующее:

  • Запускается среда реального времени.

  • Загружаются все компоненты HAL.

  • Компоненты HAL связаны друг с другом посредством сценариев .hal cmd.

  • task, iocontrol и, в конечном итоге, запускается пользовательский интерфейс.

  • До GladeVCP предполагалось, что к моменту запуска пользовательского интерфейса весь HAL загружен, подключен и готов к работе.

Внедрение GladeVCP привело к следующей проблеме:

  • Панели GladeVCP должны быть встроены в основную настройку окна графического интерфейса.

  • Панели GladeVCP должны быть встроены в основные настройки окна графического пользовательского интерфейса, например, AXIS или Touchy, Gscreen или GMOCCAPY (встроенное окно или в виде встроенной вкладки).

  • Для этого необходимо, чтобы главный ГИП был запущен до того, как окно GladeVCP можно будет подключить к главному ГИП.

  • Однако GladeVCP также является компонентом HAL и создает собственные контакты HAL.

  • Как следствие, все компоненты HAL, связанные с контактами HAL GladeVCP в качестве источника или приемника, должны запускаться после настройки ГИП.

Это задача POSTGUI_HALFILE. Эта опция INI проверяется ГИП. Если ГИП обнаруживает эту опцию, он запускает соответствующий файл HAL после настройки любой встроенной панели GladeVCP. Однако, он не проверяет, действительно ли используется панель GladeVCP, и в этом случае cmd-файл HAL запускается нормально. Поэтому, если вы НЕ запускаете GladeVCP через GLADEVCP или EMBED_TAB и т. д., но позже в отдельном окне оболочки или через какой-либо другой механизм, командный файл HAL в POSTGUI_HALFILE будет выполнен слишком рано. Предполагая, что здесь упоминаются контакты GladeVCP, это завершится неудачно с сообщением об ошибке, указывающим, что компонент GladeVCP HAL недоступен.

Итак, если вы запускаете GladeVCP из отдельного окна оболочки (т. е. не запускается встроенным ГИП):

  • Вы не можете полагаться на параметр INI POSTGUI_HALFILE, вызывающий запуск команд HAL в нужный момент времени, поэтому закомментируйте это в INI-файле.

  • Явно передайте командный файл HAL, который ссылается на контакты GladeVCP, в GladeVCP с опцией -H <halcmd file> (см. предыдущий раздел).

6. Ссылка на виджет HAL

GladeVCP включает в себя коллекцию виджетов Gtk с прикрепленными контактами HAL, называемыми виджетами HAL, предназначенными для управления, отображения или иного взаимодействия со слоем HAL LinuxCNC. Они предназначены для использования с редактором пользовательского интерфейса Glade. При правильной установке виджеты HAL должны появиться в группе виджетов Glade HAL Python. Многие поля, специфичные для HAL, в разделе General Glade имеют соответствующую всплывающую подсказку при наведении курсора мыши.

Сигналы HAL бывают двух вариантов: биты и числа. Биты — это сигналы выключения/включения. Числа могут быть типа "float", "s32" или "u32". Дополнительную информацию о типах данных HAL см. в HAL manual. Виджеты GladeVCP могут либо отображать значение сигнала с помощью виджета индикатора, либо изменять значение сигнала с помощью виджета управления. Таким образом, существует четыре класса виджетов GladeVCP, которые можно подключить к сигналу HAL. Другой класс вспомогательных виджетов позволяет вам организовывать и маркировать панель.

6.1. Именование виджетов и контактов HAL

Большинство виджетов HAL имеют один связанный контакт HAL с тем же именем HAL, что и виджет (glade: General→Name).

Исключениями из этого правила на данный момент являются:

  • HAL_Spinbutton и HAL_ComboBox, которые имеют два контакта: <widgetname>-f (float) и <widgetname>-s (s32)

  • HAL_ProgressBar, который имеет входной контакт <widgetname>-value и входной контакт <widgetname>-scale.

6.2. Атрибуты Python и методы HAL Widgets

Виджеты HAL являются экземплярами GtKWidgets и, следовательно, наследуют методы, свойства и сигналы применимого класса GtkWidget. Например, чтобы выяснить, какие методы, свойства и сигналы, связанные с GtkWidget, имеет HAL_Button, найдите описание https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Button.html. Gtk.Button[GtkButton] в Справочник по API PyGObject.

Простой способ узнать отношение наследования данного виджета HAL заключается в следующем: запустите Glade, поместите виджет в окно и выберите его; затем выберите вкладку Signals в окне Properties. Например, если выбрать виджет «HAL_LED», это покажет, что HAL_LED является производным от GtkWidget, который, в свою очередь, является производным от GtkObject и, в конечном итоге, от GObject.

Полную иерархию классов можно увидеть, вызвав GtkInspector в графическом интерфейсе Glade, выбрав виджет и нажав Control-Shift-I. Если Инспектор не открывается, он может быть разрешен из терминала, введя:

gsettings set org.gtk.Settings.Debug enable-inspector-keybinding true

Инспектор также удобен для тестирования изменений стиля CSS "на лету", а также для определения всех свойств и сигналов, доступных для виджета.

Виджеты HAL также имеют несколько атрибутов Python, специфичных для HAL:

hal_pin

Базовый объект Python контакта HAL в случае, если виджет имеет один тип контакта

hal_pin_s, hal_pin_f

Контакты s32 и float виджетов HAL_Spinbutton и HAL_ComboBox — обратите внимание, что эти виджеты не имеют атрибута hal_pin!

hal_pin_scale

Входной контакт с плавающей запятой виджета HAL_ProgressBar, представляющий максимальное абсолютное значение ввода.

Существует несколько методов HAL Widgets, специфичных для HAL, но единственный подходящий метод:

<halpin>.get()

Получите значение текущего контакта HAL, где <halpin> — это соответствующее имя контакта HAL, указанное выше.

6.3. Установка значений контактов и виджетов

Как правило, если вам нужно установить значение выходного виджета HAL из кода Python, сделайте это, вызвав базовый setter Gtk (например, set_active(), set_value()). Не пытайтесь установить значение связанного контакта напрямую с помощью halcomp[pinname] = value, потому что виджет не заметит это изменение!

Может возникнуть соблазн программно установить входные контакты виджета HAL. Обратите внимание, что это в первую очередь противоречит назначению входного контакта — он должен быть связан с сигналами, генерируемыми другими компонентами HAL, и реагировать на них. Хотя в настоящее время в HAL Python нет защиты от записи на входные контакты, это не имеет смысла. Однако вы можете использовать setp _pinname_ _value_ в связанном файле HAL для тестирования.

Совершенно нормально установить значение выходного контакта HAL с помощью halcomp[pinname] = value при условии, что этот контакт HAL не связан с виджетом, то есть был создан hal_glib.GPin(halcomp.newpin(<name>,<type>,<direction>)) (пример см. в GladeVCP Programming).

6.4. Сигнал hal-pin-changed

Программирование, управляемое событиями, означает, что пользовательский интерфейс сообщает вашему коду, когда "что-то происходит" — посредством обратного вызова, например, при нажатии кнопки. Выходные виджеты HAL (те, которые отображают значение контакта HAL), такие как LED, Bar, VBar, Meter и т. д., поддерживают сигнал hal-pin-changed, который может вызвать обратный вызов вашего кода Python, когда - ну, контакт HAL меняет свое значение. Это означает, что больше нет необходимости постоянно опрашивать изменения контактов HAL в вашем коде: виджеты делают это в фоновом режиме и сообщают вам об этом.

Вот пример установки сигнала hal-pin-changed для HAL_LED в редакторе Glade UI:

images/hal-pin-change-66.png

Пример в configs/apps/gladevcp/complex показывает, как это обрабатывается в Python.

6.5. Кнопки

Эта группа виджетов является производной от различных кнопок Gtk и состоит из виджетов HAL_Button, HAL_ToggleButton, HAL_RadioButton и CheckButton. Все они имеют один выходной BIT контакт, имя которого идентично имени виджета. Кнопки не имеют дополнительных свойств по сравнению с их базовыми классами Gtk.

  • HAL_Button: мгновенное действие, не сохраняет состояние. Важный сигнал: pressed

  • HAL_ToggleButton, HAL_CheckButton: сохраняет состояние вкл/выкл. Важный сигнал: toggled

  • HAL_RadioButton: группа одна из многих. Важный сигнал: toggled (для каждой кнопки).

  • Важные общие методы: set_active(), get_active()

  • Важные свойства: label, image

images/checkbutton.png
Figure 1. Кнопка независимой фиксации
images/radiobutton.png
Figure 2. Кнопки зависимой фиксации
images/button.png
Figure 3. Кнопка-переключатель
Tip

Определение группы кнопок зависимой фиксации в Glade:

  • Выберите активную кнопку по умолчанию.

  • В разделе General→Group другой кнопки выберите имя активной кнопки по умолчанию в диалоговом окне Choose a Radio Button in this project.

См. configs/apps/gladevcp/by-widget/ для приложений GladeVCP и файла пользовательского интерфейса для работы с кнопками зависимой фиксации.

6.6. Шкалы

HAL_HScale и HAL_VScale являются производными от GtkHScale и GtkVScale соответственно.

<widgetname>

выходной FLOAT контакт

<widgetname>-s

выходной s32 контакт

Чтобы сделать шкалу полезной в Glade, добавьте Adjustment (General → Adjustment → New or existing adjustment) и отредактируйте объект настройки. Он определяет значения default/min/max/increment. Кроме того, установите настройки Page size и Page increment на ноль, чтобы избежать предупреждений.

images/hscale.png
Figure 4. Пример HAL_HScale

6.7. Окошко счетчика

HAL SpinButton является производным от GtkSpinButton и содержит два контакта:

<widgetname>-f

выходной FLOAT контакт

<widgetname>-s

выходной s32 контакт

Чтобы быть полезными, Spinbuttons необходимо значение настройки, такое как шкала, см. выше.

images/spinbutton.png
Figure 5. Пример SpinButton

6.8. Hal_Dial

Виджет hal_dial имитирует маховичок или регулировочный циферблат.
Им можно управлять с помощью мыши. Вы можете просто использовать колесо мыши, пока курсор мыши находится над виджетом Hal_Dial, или удерживать левую кнопку мыши и перемещать курсор по кругу, чтобы увеличить или уменьшить отсчеты.
Двойным щелчком левой или правой кнопки масштабный коэффициент можно увеличить или уменьшить.

  • Против часовой стрелки = уменьшить отсчеты

  • По часовой стрелке = увеличить отсчеты

  • Колесо вверх = увеличение отсчетов

  • Колесо вниз = уменьшить отсчеты

  • Двойной щелчок левой кнопкой мыши = масштаб x10

  • Двойной щелчок правой кнопкой мыши = масштаб /10

6.8.1. Контакты

hal_dial экспортирует свое значение отсчетов в виде контактов HAL:

<widgetname>

выходной s32 контакт

<widgetname>-scaled

выходной FLOAT контакт

<widgetname>-delta-scaled

выходной FLOAT контакт

6.8.2. Свойства

hal_dial имеет следующие свойства:

cpr

Устанавливает количество отсчетов на оборот, допустимые значения находятся в диапазоне от 25 до 360.
по умолчанию = 100

show_counts

Установите в False, если вы хотите скрыть отображение отсчетов в середине виджета.
по умолчанию = True

label

Установите содержимое метки, которая может отображаться поверх значения отсчетов.
Если длина метки превышает 15 символов, она будет сокращена до 15 символов.
по умолчанию = пусто

center_color

Это позволяет изменить цвет колеса. Он использует цветовую строку GDK.
по умолчанию = #bdefbdefbdef (серый)

count_type_shown

Доступны три вида отсчетов: 0) Необработанные отсчеты CPR 1) Масштабированные отсчеты 2) Дельта-масштабированные отсчеты.
по умолчанию = 1

  • отсчет основан на выбранном CPR – он будет считаться положительным и отрицательным. Он доступен в виде контакта s32.

  • Масштабированный отсчет – это отсчет CPR , умноженный на масштаб – он может быть положительным и отрицательным.
    Если вы измените масштаб, выходные данные немедленно отразят это изменение. Он доступен в виде контакта FLOAT.

  • Дельта-масштабированный-отсчет — это ИЗМЕНЕНИЕ количества CPR, с коэффициентом масштаба.
    Если вы измените масштаб, только отсчеты после этого изменения будут масштабированы, а затем добавлены к текущему значению.
    Он доступен в виде контакта FLOAT.

scale_adjustable

Установите для этого параметра значение False, если вы хотите запретить изменение масштаба двойным щелчком по виджету.
Если это значение неверно, коэффициент масштаба не будет отображаться в виджете.
по умолчанию = True

scale

Установите это для масштабирования отсчетов.
по умолчанию = 1.0

6.8.3. Прямое управление программой

Существуют способы прямого управления виджетом с помощью Python.

Использование goobject для установки перечисленных выше свойств:

[widget name].set_property("cpr",int(value))
[widget name].set_property("show_counts, True)
[widget name].set_property("center_color",gtk.gdk.Color('#bdefbdefbdef'))
[widget name].set_property('label', 'Test Dial 12345')
[widget name].set_property('scale_adjustable', True)
[widget name].set_property('scale', 10.5)
[widget name].set_property('count_type_shown', 0)

Существуют методы Python:

  • [widget name].get_value()
    Вернет значение счетчика как целое число s32

  • [widget name].get_scaled_value()
    Вернет отсчеты в виде числа с плавающей запятой

  • [widget name].get_delta_scaled_value()
    Вернет отсчеты в виде числа с плавающей запятой

  • [widget name].set_label("string")
    Устанавливает содержимое метки с помощью "string"

Выдается два сигнала GObject:

  • count_changed
    Генерируется, когда изменяются отсчеты виджета, например, от прокрутки колеса.

  • scale_changed
    Генерируется, когда изменяется масштаб виджета, например, от двойного щелчка.

Подключитесь к ним следующим образом:

[widget name].connect('count_changed', [count function name])
[widget name].connect('scale_changed', [scale function name])

Функции обратного вызова будут использовать этот шаблон:

def [count function name](widget, count,scale,delta_scale):

Это вернет: widget, current count, scale и delta scale этого виджета.

images/Hal_Dial.png
Figure 6. Пример Hal_Dial

6.9. Маховичок подачи

Виджет jogwheel имитирует настоящий маховичок. Им можно управлять с помощью мыши. Вы можете просто использовать колесо мыши, пока курсор мыши находится над виджетом JogWheel, или нажать левую кнопку мыши и перемещать курсор по кругу, чтобы увеличить или уменьшить отсчеты.

  • Против часовой стрелки = уменьшить отсчеты

  • По часовой стрелке = увеличить отсчеты

  • Колесико вверх = увеличить отсчеты

  • Колесико вниз = уменьшить отсчеты

Поскольку перемещение мыши при перетаскивании может происходить быстрее, чем виджет может обновиться, вы можете потерять отсчеты и крутя слишком быстро. Рекомендуется использовать колесико мыши и только при очень грубых изменениях — способ перетаскивания.

6.9.1. Контакты

jogwheel экспортирует свое значение счетчика как контакт HAL:

<widgetname>-s

выходной s32 контакт

6.9.2. Свойства

jogwheel имеет следующие свойства:

size

Устанавливает размер виджета в пикселях, допустимые значения находятся в диапазоне от 100 до 500, по умолчанию = 200

cpr

Устанавливает количество отсчетов на оборот, допустимые значения находятся в диапазоне от 25 до 100, по умолчанию = 40

show_counts

Установите в False, если вы хотите скрыть отображение отсчетов в середине виджета.

label

Установите содержимое метки, которая может отображаться поверх значения отсчетов. Цель состоит в том, чтобы дать пользователю представление об использовании этого маховичка. Если длина метки превышает 12 символов, она будет сокращена до 12 символов.

6.9.3. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование GObject для установки перечисленных выше свойств:

[widget name].set_property("size",int(value))
[widget name].set_property("cpr",int(value))
[widget name].set_property("show_counts, True)

Существует два метода Python:

  • [widget name].get_value()
    Вернет значение отсчетов как целое число

  • [widget name].set_label("string")
    Устанавливает содержимое метки с помощью "string"

images/JogWheel.png
Figure 7. Пример JogWheel

6.10. Контроль скорости

speedcontrol — это виджет, специально созданный для управления регулировкой с помощью сенсорного экрана. Это замена виджета обычного масштаба, который сложно перемещать по сенсорному экрану.

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

6.10.1. Контакты

speedcontrol предлагает некоторые контакты HAL:

<widgetname>-value

выходной float контакт
Отображаемое значение виджета.

<widgetname>-scaled-value

выходной float контакт
Отображаемое значение делится на значение масштаба. Это очень полезно, если скорость отображается в единицах/мин, но LinuxCNC ожидает, что она будет в единицах/секунду.

<widgetname>-scale

входной float контакт
Применяемый масштаб.
По умолчанию — 60.

<widgetname>-increase

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

<widgetname>-decrease

входной bit контакт
Пока контакт true, значение будет уменьшаться.
Очень удобно с подключенным переключателем мгновенного действия.

6.10.2. Свойства

speedcontrol имеет следующие свойства:

height

Integer
Высота виджета в пикселях.
Допустимые значения: от 24 до 96.
По умолчанию — 36.

value

Float
Начальное значение для установки.
Допустимые значения находятся в диапазоне от 0,001 до 99999,0.
По умолчанию — 10.0.

min

Float
Минимально допустимое значение.
Допустимые значения: от 0,0 до 99999,0.
По умолчанию — 0,0.
Если вы измените это значение, приращение будет сброшено до значения по умолчанию, поэтому может потребоваться впоследствии установить новое приращение.

max

Float
Максимально допустимое значение.
Допустимые значения: от 0,001 до 99999,0.
По умолчанию — 100,0.
Если вы измените это значение, приращение будет сброшено до значения по умолчанию, поэтому может потребоваться впоследствии установить новое приращение.

increment

Float
Устанавливает применяемое приращение за клик мышки.
Допустимые значения: от 0,001 до 99999,0 и -1.
По умолчанию установлено значение -1, что приводит к увеличению значения на 100 от минимального до максимального.

inc_speed

Integer
Устанавливает задержку таймера для увеличения скорости, удерживая нажатыми кнопки.
Допустимые значения: от 20 до 300.
По умолчанию — 100.

unit

String
Устанавливает единицу измерения, отображаемую на панели после значения.
Допускается любая строка.
По умолчанию — "".

color

Color
Устанавливает цвет полосы.
Допускается любой шестнадцатеричный цвет.
По умолчанию — "#FF8116".

template

String
Текстовый шаблон для отображения значения. Используется форматирование Python.
Любой разрешенный формат.
По умолчанию – "%.1f".

do_hide_button

Boolean
Показывать или скрывать увеличение кнопки уменьшения.
True или False.
По умолчанию = False.

6.10.3. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование GObject для установки перечисленных выше свойств:

[widget name].set_property("do_hide_button",bool(value))
[widget name].set_property("color","#FF00FF")
[widget name].set_property("unit", "mm/min")
etc.

Существуют также методы Python для изменения виджета:

[widget name].set_adjustment(gtk-adjustment)

Вы можете назначить существующую настройку элементу управления, чтобы можно было легко заменить существующие ползунки без большого количества изменений кода. Имейте в виду, что после изменения настройки вам может потребоваться установить новый шаг, поскольку он будет сброшен до значения по умолчанию (100 шагов от MIN до MAX):

  • [widget name].get_value()
    Вернет значение отсчетов как число с плавающей запятой

  • [widget name].set_value(float(value))
    Устанавливает виджет на заданное значение

  • [widget name].set_digits(int(value))
    Устанавливает цифры значения, которое будет использоваться

  • [widget name].hide_button(bool(value))
    Скрыть или показать кнопку

images/SpeedControl.png
Figure 8. Пример Speedcontrol

6.11. Label

hal_label — это простой виджет, основанный на GtkLabel, который представляет значение контакта HAL в определяемом пользователем формате.

label_pin_type

Тип HAL вывода (0:s32, 1:float, 2:u32), см. также всплывающую подсказку General→HAL pin type (обратите внимание, что это отличается от PyVCP, который имеет три виджета меток, по одному для каждого типа).

text_template

Определяет отображаемый текст - строку формата Python для преобразования значения контакта в текст. По умолчанию %s (значения преобразуются функцией str()), но может содержать любой допустимый аргумент в качестве аргумента метода Python format().
Пример: Distance: %.03f отобразит текст и значение контакта с 3 дробными цифрами, дополненными нулями для контакта FLOAT.

6.12. Контейнеры

  • HAL_HideTable

  • HAL_Table

  • State_Sensitive_Table

  • HAL_HBox (устарело)

Эти контейнеры предназначены для десенсибилизации (серого цвета) или сокрытия их детей.
Нечувствительные потомки не будут реагировать на вводимые данные.

HAL_HideTable

Имеет один входной контакт HAL BIT, который контролирует, скрыты ли его дочерние виджеты или нет.

Pin:
<Panel_basename>.<widgetname>

in bit pin
Если контакт имеет низкий логический уровень, то видны дочерние виджеты, что является состоянием по умолчанию.

HAL_Table и HAL_Hbox

Имеют один входной контакт HAL BIT, который контролирует, являются ли их дочерние виджеты чувствительными или нет.

Pin:
<Panel_basename>.<widgetname>

in bit pin
Если на контакте низкий логический уровень, дочерние виджеты неактивны, что является состоянием по умолчанию.

State_Sensitive_Table

Отвечает на состояние интерпретатора LinuxCNC.
При необходимости можно выбрать реакцию на must-be-all-homed, must-be-on and must-be-idle.
Вы можете объединить их. В Estop всегда будет нечувствительно.
(Не имеет контакта).

Warning
HAL_Hbox устарел — используйте HAL_Table.
Если текущие панели используют его, он не подведет. Вы просто больше не найдете его в редакторе GLADE.
В будущих версиях GladeVCP этот виджет может быть полностью удален, и тогда вам придется обновить панель.
Tip

Если вы обнаружите, что какая-то часть вашего приложения GladeVCP grayed out (нечувствительна), посмотрите, не сброшен ли или не подключен контакт HAL_Table.

6.13. LED

hal_led имитирует настоящий светодиодный индикатор.
Он имеет один входной контакт BIT, который контролирует его состояние: ВКЛ или ВЫКЛ.

6.13.1. Свойства

СИДы имеют несколько свойств, которые определяют их внешний вид:

on_color

Строка, определяющая цвет ВКЛ состояния СИД.
Может быть любым допустимым именем gdk.Color.
Не работает на Ubuntu 8.04.

off_color

Строка, определяющая цвет ВЫКЛ состояния СИД.
Может быть любым допустимым именем gdk.Color или специальным значением dark . dark означает, что цвет ВЫКЛ будет установлен на значение 0,4 цвета ВКЛ.
Не работает на Ubuntu 8.04.

pick_color_on, pick_color_off

Цвета для состояний ВКЛ и ВЫКЛ.
Они могут быть представлены как строки #RRRRGGGGBBBB и являются необязательными свойствами, имеющими приоритет над on_color и off_color.

led_size

Радиус СИД (для квадратного - половина стороны СИД)

led_shape

Форма СИД.
Допустимые значения: 0 для круглой формы, 1 для овала и 2 для квадратной формы.

led_blink_rate

Если установлено и СИД в состоянии ВКЛ, тогда он мигает.
Период мигания равен значению "led_blink_rate", указанному в миллисекундах.

create_hal_pin

Выбор/отмена создания контакта HAL для управления СИД.
Без созданного контакта HAL СИД'ом можно управлять с помощью функции Python.

6.13.2. Сигналы

В качестве виджета ввода LED также поддерживает сигнал hal-pin-changed. Если вы хотите получать в своем коде уведомление при изменении контакт HAL LED, подключите этот сигнал к обработчику, например on_led_pin_changed, и укажите обработчик следующим образом:

def on_led_pin_changed(self,hal_led,data=None):
    print("on_led_pin_changed() - HAL pin value:",hal_led.hal_pin.get())

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

images/leds.png
Figure 9. Пример СИД'ов

6.14. ProgressBar

Note

Этот виджет может исчезнуть.
Вместо этого используйте виджеты HAL_HBar и HAL_VBar.

6.14.1. Контакты

HAL_ProgressBar является производным от gtk.ProgressBar и имеет два входных float контакта HAL:

<widgetname>

текущее значение, которое будет отображаться

<widgetname>-scale

максимальное абсолютное значение ввода

6.14.2. Свойства

HAL_ProgressBar имеет следующие свойства:

scale

Шкала значений.
Устанавливает максимальное абсолютное значение входа. То же, что и установка контакта <widgetname>.scale.
Число с плавающей запятой, диапазон от -224 до +224.

green_limit

Нижний предел зеленой зоны

yellow_limit

Нижний предел желтой зоны

red_limit

Нижний предел красной зоны

text_template

Текстовый шаблон для отображения текущего значения контакта <widgetname>.
Форматирование Python может использоваться для dict {"value":value}.

images/progressbar2.png
Figure 10. Пример HAL_ProgressBar

6.15. ComboBox

HAL_ComboBox является производным от gtk.ComboBox. Позволяет выбрать значение из раскрывающегося списка.

6.15.1. Контакты

HAL_ComboBox экспортирует два контакта HAL:

<widgetname>-f

Текущее значение, тип FLOAT

<widgetname>-s

Текущее значение, тип s32

6.15.2. Свойства

HAL_ComboBox имеет следующее свойство, которое можно установить в Glade:

column

Индекс столбца.
Тип s32.
Допустимый диапазон: -1..100.
Значение по умолчанию -1.

В режиме по умолчанию этот виджет устанавливает контакты в индекс выбранной записи списка. Таким образом, если ваш виджет имеет три метки, он может принимать только значения 0,1 и 2.

В режиме столбца (column > -1) сообщаемое значение выбирается из массива ListStore, как определено в Glade. Поэтому обычно определение вашего виджета будет иметь два столбца в ListStore, один с текстом, отображаемым в раскрывающемся списке, и значение int или float, используемое для этого выбора.

В configs/apps/by-widget/combobox.{py,ui} есть пример, который использует режим столбца для выбора значения float из ListStore.

Если вы, как и я, не понимаете, как редактировать ComboBox ListStore и CellRenderer, см. https://youtu.be/Z5_F-rW2cL8.

6.16. Шкалы

Виджеты HAL_Bar и HAL_VBar для горизонтальных и вертикальных шкал, представляющих значения с плавающей запятой.

6.16.1. Контакты

HAL_Bar и HAL_VBar имеют по одному входному конаткту FLOAT HAL.

6.16.2. Свойства

HAL_Bar и HAL_VBar обе шкалы имеют следующие свойства:

invert

Меняет местами min и max направления.
Инвертированный HBar растет справа налево, инвертированный VBar — сверху вниз.

min, max

Минимальное и максимальное значение желаемого диапазона. Если текущее значение находится за пределами этого диапазона, это не является ошибкой.

show limits

Используется для выбора/отмены выбора ограничений текста на панели.

zero

Нулевая точка диапазона.
Если она находится в пределах min/max диапазона, полоса будет расти от этого значения, а не от левой (или правой) стороны виджета.
Полезно для представления значений, которые могут быть как положительными, так и отрицательными.

force_width, force_height

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

text_template

Как и в Label, устанавливает текстовый формат для min/max/current значений.
Может использоваться для отключения отображения значений.

value

Устанавливает отображение шклы в соответствии с введенным значением.
Используется только для тестирования в редакторе GLADE.
Значение будет установлено с контакта HAL.

target value

Устанавливает целевую линию на введенное значение.
Используется только для тестирования в редакторе GLADE.
Значение можно установить в функции Python.

target_width

Ширина линии, обозначающей целевое значение.

bg_color

Цвет фона (неактивного) шкалы.

target_color

Цвет целевой линии.

z0_color, z1_color, z2_color

Цвета зон разных значений.
По умолчанию: green, yellow and red.
Описание зон смотрите в свойствах z*_border.

z0_border, z1_border

Определите границы цветовых зон.
По умолчанию включена только одна зона. Если вам нужно больше одной зоны, установите для z0_border и z1_border нужные значения, чтобы зона 0 заполнялась от 0 до первой границы, зона 1 заполнялась от первой до второй границы, а зона 2 — от последней границы до 1.
Границы задаются в виде дробей.
Допустимые значения находятся в диапазоне от 0 до 1.

images/hal_hbar.png
Figure 11. Горизонтальная шкала
images/vscale.png
Figure 12. Вертикальная шкала

6.17. Meter

HAL_Meter — это виджет, похожий на счетчик PyVCP, он представляет собой значение с плавающей запятой.

6.17.1. Контакты

HAL_Meter имеет один входной FLOAT контакт HAL.

6.17.2. Свойства

HAL Meter имеет следующие свойства:

min, max

Минимальное и максимальное значение желаемого диапазона.
Если текущее значение находится за пределами этого диапазона, это не является ошибкой.

force_size

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

text_template

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

label

Большая этикетка над центром циферблата.

sublabel

Маленькая этикетка под центром циферблата.

bg_color

Цвет фона циферблата.

z0_color, z1_color, z2_color

Цвета зон разных значений.
По умолчанию: green, yellow and red.
Описание зон смотрите в свойствах z*_border.

z0_border, z1_border

Определите границы цветовых зон.
По умолчанию включена только одна зона. Если вам нужно более одной зоны, установите для z0_border и z1_border нужные значения, чтобы зона 0 заполнялась от минимальной до первой границы, зона 1 заполнялась от первой до второй границы, а зона 2 — от последней границы до максимальной.
Границы задаются как значения в диапазоне min-max.

images/hal_meter.png
Figure 13. Пример HAL Циферблатов

6.18. HAL_Graph

Этот виджет предназначен для построения временного графика значений.

6.19. Предварительный просмотр пути инструмента Gremlin для файлов NGC

Gremlin — это виджет предварительного просмотра сюжета, похожий на окно предварительного просмотра AXIS. Предполагается работающая среда LinuxCNC, такая как AXIS или Touchy. Чтобы подключиться к нему, проверяет переменную среды INI_FILE_NAME. Gremlin отображает текущий файл NGC — он отслеживает изменения и перезагружает файл ngc, если имя файла в AXIS/Touchy меняется. Если вы запустите его в приложении GladeVCP, когда LinuxCNC не запущен, вы можете получить обратную трассировку, поскольку виджет Gremlin не может найти статус LinuxCNC, например текущее имя файла.

6.19.1. Контакты

Gremlin не экспортирует контакты HAL.

6.19.2. Свойства

Гремлин имеет следующие свойства:

enable_dro

Это отобразит УЦИ на графике.
По умолчанию = true.

show_velocity

Здесь отображается скорость инструмента.
По умолчанию = true.

use_commanded

Это выбирает режим УЦИ, который будет использоваться: заданные или фактические значения.
По умолчанию = true.

metric_units

Этот параметр выбирает режим УЦИ, который будет использоваться: метрические или имперские единицы.
По умолчанию = true.

show_rapids

Это говорит плоттеру показывать быстрые движения.
По умолчанию = true.

show_dtg_

Это выбирает режим УЦИ для отображения значения оставшегося пути.
По умолчанию = true.

use_relative

Это выбирает режим УЦИ для отображения значений относительно пользовательской системы или координат станка.
По умолчанию = true.

show_live_plot

Это говорит плоттеру, рисовать или нет.
По умолчанию = true.

show_limits

Это говорит плоттеру показать пределы станка.
По умолчанию = true.

show_lathe_radius

Выбирает режим УЦИ для отображения оси X в радиусе или диаметре, если в режиме токарного станка (выбирается в INI-файле с LATHE = 1).
По умолчанию = true.

show_extents_option

Это указывает плоттеру показать возможности станка.
По умолчанию = true.

show_tool

Это указывает плоттеру нарисовать инструмент.
По умолчанию = true.

show_program

Показывает программу G-кода.
По умолчанию = True

use_joints_mode

Используется со станками c non trivialkins кинематикой (например, роботах).
По умолчанию = false.

grid_size

Устанавливает размер сетки (виден только в видах X, Y и Z).
По умолчанию 0

use_default_controls

Это запрещает элементы управления мышью по умолчанию.
Это наиболее полезно при использовании сенсорного экрана, поскольку элементы управления по умолчанию работают некорректно. Вы можете программно добавлять элементы управления, используя Python и метод файла-обработчика.
По умолчанию = true.

view

Может быть любым из x, y, y2 , z, z2 , p (перспектива).
По умолчанию используется вид z.

enable_dro

Тип = boolean.
Отрисовывать УЦИ на выводе или нет.
По умолчанию = true.

mouse_btn_mode

Тип = integer.
Обработка кнопок мыши: приводит к различным функциям кнопки:

  • 0 = по умолчанию: левая вращение, средняя перемещение, правая масштабирование

  • 1 = левая масштабирование , средняя перемещение, правая вращение

  • 2 = левая перемещение, средняя вращение, правая масштабирование

  • 3 = левая масштабирование, средняя вращение, правая перемещение

  • 4 = левая перемещение, средняя масштабирование, правая вращение

  • 5 = левая вращение, средняя масштабирование, правая перемещение

  • 6 = левая перемещение, средняя масштабирование, правая масштабирование

Режим 6 рекомендуется для плазменных и токарных станков, поскольку для таких станков вращение не требуется.

6.19.3. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование GObject для установки перечисленных выше свойств:

[widget name].set_property('view','P')
[widget name].set_property('metric_units',False)
[widget name].set_property('use_default_controls',False)
[widget name].set_property('enable_dro' False)
[widget name].set_property('show_program', False)
[widget name].set_property('show_limits', False)
[widget name].set_property('show_extents_option', False)
[widget name].set_property('show_live_plot', False)
[widget name].set_property('show_tool', False)
[widget name].set_property('show_lathe_radius',True)
[widget name].set_property('show_dtg',True)
[widget name].set_property('show_velocity',False)
[widget name].set_property('mouse_btn_mode', 4)

Существуют методы Python:

[widget name].show_offsets = True
[widget name].grid_size = .75
[widget name].select_fire(event.x,event.y)
[widget name].select_prime(event.x,event.y)
[widget name].start_continuous_zoom(event.y)
[widget name].set_mouse_start(0,0)
[widget name].gremlin.zoom_in()
[widget name].gremlin.zoom_out()
[widget name].get_zoom_distance()
[widget name].set_zoom_distance(dist)
[widget name].clear_live_plotter()
[widget name].rotate_view(x,y)
[widget name].pan(x,y)
Подсказки
  • Если вы установите для всех параметров построения графиков значение false, а для show_offsets значение true, вы получите страницу смещений вместо отрисовки графика.

  • Если вы получите расстояние масштабирования перед изменением вида, а затем сбросите расстояние масштабирования, это будет намного удобнее для пользователя.

  • если вы выберете элемент в предварительном просмотре, выбранный элемент будет использоваться в качестве центральной точки вращения

images/gremlin.png
Figure 14. Пример Gremlin

6.20. HAL_Offset

Виджет HAL_Offset используется для отображения смещения одной оси.

6.20.1. Свойства

HAL_Offset имеет следующие свойства:

display_units_mm

Отображение в метрических единицах.

joint_number

Используется для выбора отображаемой оси (технически какое сочленение).
На станке с trivialkins (фрезерный, токарный) ось vs. номер сочленения имеют следующие комбинации:

0:X 1:Y 2:Z 3:A 4:B 5:C 6:U 7:V 8:W
mm_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.

imperial_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.

reference_type
0:G5x 1:tool 2:G92 3:Rotation around Z

6.21. Виджет УЦИ

Виджет УЦИ используется для отображения текущего положения оси.

6.21.1. Свойства

Он имеет следующие свойства:

display_units_mm

Используется для переключения единиц отображения между метрическими и имперскими. По умолчанию — False.

actual

Выбирает фактическое положение (обратная связь) или заданное положение. По умолчанию — True.

diameter

Отображает диаметр для токарного станка. По умолчанию — False.

mm_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью. По умолчанию — "%10.3f".

imperial_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью. По умолчанию — "%9.4f".

joint_number

Используется для выбора отображаемой оси (технически какое сочленение). По умолчанию — 0.
На станке с кинематикой trivialkins (фрезерный, токарный) сочетание ось и номер сочленения следующие:

0:X 1:Y 2:Z 3:A 4:B 5:C 6:U 7:V 8:W +
reference_type
  • 0 = absolute (исходное положение станка).

  • 1 = relative (к началу координат текущего пользователя - G5x).

  • 2 = distance-to-go (относительно начала координат текущего пользователя). По умолчанию — 0.

font_family

Укажите семейство шрифтов, например. mono. По умолчанию sans. Если шрифт не существует, будет использоваться текущий системный шрифт. По умолчанию — sans.

font_size

Укажите размер шрифта от 8 до 96. По умолчанию — 26.

font_weight

Укажите вес шрифта. Выберите lighter, normal, bold, or bolder. По умолчанию - bold.

unhomed_color

Цвет текста, когда вне исходной позиции, указан как цвет Gdk.RGBA. По умолчанию — красный, Gdk.RGBA(красный=1.000000, зеленый=0.000000, синий=0.000000, альфа=1.000000)

homed_color

Цвет текста когда в исходной позиции указан как цвет Gdk.RGBA. По умолчанию — зеленый, Gdk.RGBA(красный=0,000000, зеленый=0,501961, синий=0,000000, альфа=1,000000)

Подсказки
  • Если вы хотите, чтобы изображение было выровнено по правому краю, установите для параметра Horizontal Alignment значение End.

  • Фон виджета на самом деле прозрачный, поэтому, если вы поместите его поверх изображения, числа УЦИ будут отображаться поверх него без фона. Для этого существует специальная техника. См. анимированные функциональные схемы ниже.

  • Виджет DRO — это модифицированный виджет меток GTK. Таким образом, многое из того, что можно сделать с меткой gtk, можно сделать и с виджетом DRO.

  • Свойства шрифта также могут быть установлены из таблицы стилей CSS, которая имеет наивысший приоритет и переопределяет значения, установленные свойствами GObject.

6.21.2. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование GObject для установки перечисленных выше свойств
[widget name].set_property("display_units_mm", True)
[widget name].set_property("actual", True)
[widget name].set_property("diameter", True)
[widget name].set_property("mm_text_template", "%10.3f")
[widget name].set_property("imperial_text_template", "%9.4f")
[widget name].set_property("joint_number", 3)
[widget name].set_property("reference_type", 3)
[widget name].set_property("font_family", "mono")
[widget name].set_property("font_size", 30)
[widget name].set_property("font_weight", "bold")
# it is easier to read colors by calling a function:
def str_to_rgba(color):
  c = Gdk.RGBA()
  c.parse(color)
  return c

[widget name].set_property("unhomed_color", str_to_rgba("magenta"))
[widget name].set_property("homed_color", str_to_rgba("cyan"))
Использование таблицы стилей CSS для установки свойств шрифта

Цвета могут быть указаны в одном из нескольких форматов, все они будут указывать один и тот же цвет: красный, *#ff0000, *rgb(255,0,0) или rgba(255,0,0,255).

Цвета могут упоминаться либо вместе:

.dro_unhomed {color: magenta}
.dro_homed {color: cyan}

или индивидуально по названию виджета:

#[widget name].dro_unhomed {color: magenta}
#[widget name].dro_homed {color: cyan}

На другие свойства стиля необходимо ссылаться по имени виджета:

#[widget name], #[widget name], #[widget name] {
    font-family: mono;
    font-size: 60px;
    font-weight: lighter;
}
Существует два метода Python
[widget name].set_dro_inch()
[widget name].set_dro_metric()

6.22. Виджет Combi_DRO

Виджет Combi_DRO используется для отображения текущего положения, положения относительной оси и расстояния, которое необходимо пройти в одном УЦИ.
При нажатии на УЦИ порядок УЦИ будет переключаться.
В Relative Mode будет отображаться фактическая система координат.

6.22.1. Свойства

Combi_DRO имеет следующие свойства:

joint_number

Используется для выбора отображаемой оси (технически какое сочленение).
На станке с кинематикой trivialkins (фрезерный, токарный) номера осей/сочленений следующие:

0:X 1:Y 2:Z etc.
actual

Выберите фактическое (обратная связь) или заданное положение.

metric_units

Используется для переключения между отображением метрических и имперских единиц.

auto_units

Единицы измерения будут переключаться между метрическими и имперскими единицами в зависимости от того, какой активный G-код — G20 или G21.
По умолчанию — TRUE.

diameter

Отображать положение в виде диаметра или радиуса.
В режиме диаметра УЦИ отобразит значение сочленения, умноженное на 2.

mm_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.
По умолчанию — "%10.3f".

imperial_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.
По умолчанию — "%9.4f".

homed_color

Цвет переднего плана чисел УЦИ, если сочленение находится в исходной позиции.
По умолчанию - зеленый.

unhomed_color

Цвет переднего плана чисел УЦИ, если сочленение не находится в исходной позиции.
По умолчанию красный.

abs_color

Цвет фона УЦИ, если основной УЦИ показывает абсолютные координаты.
По умолчанию синий.

rel_color

Цвет фона УЦИ, если основной УЦИ показывает относительные координаты.
По умолчанию черный.

dtg_color

Цвет фона УЦИ, если основной УЦИ показывает оставшееся расстояние.
По умолчанию желтый.

font_size

Размер шрифта больших цифр, у маленьких будет в 2,5 раза меньше.
Значение должно быть целым числом в диапазоне от 8 до 96.
По умолчанию 25.

toggle_readout

Щелчок левой кнопкой мыши переключает показания УЦИ в различные режимы ["Rel", "Abs", "DTG"].
Сняв флажок, вы можете запретить это поведение. Переключение по-прежнему можно выполнить с помощью [widget name].toggle_readout().
Значение должно быть boolean.
По умолчанию — TRUE.

cycle_time

Время ожидания DRO между двумя опросами.
Эту настройку следует изменять только в том случае, если вы используете более 5 УЦИ одновременно, т. е. в конфигурации с 6 осями, чтобы избежать слишком сильного замедления основного приложения УЦИ.
Значение должно быть целым числом в диапазоне от 100мс до 1000мс.
По умолчанию — 150.

6.22.2. Прямое управление программой

Использование GObject для установки перечисленных выше свойств:

[widget name].set_property(property, value)

Существует несколько методов Python для управления виджетом:

  • [widget name].set_to_inch(state)
    Устанавливает УЦИ для отображения имперских единиц.
    state = boolean (True or False)
    По умолчанию FIXME.

  • [widget name].set_auto_units(state)
    Если в True, УЦИ изменит единицы измерения в соответствии с активным G-кодом (G20 / G21).
    state = boolean (True or False)
    По умолчанию True.

  • [widget name].set_to_diameter(state)
    Если True, УЦИ будет показывать диаметр, а не радиус, т. е. значение оси, умноженное на 2 (особенно необходимо для токарных станков).
    state = boolean (True or False)
    По умолчанию False.

  • [widget name].toggle_readout()
    Переключает порядок УЦИ в виджете.

  • [widget name].change_axisletter(letter)
    Изменяет автоматически заданную букву оси.
    Очень полезно изменить УЦИ токарного станка с X to R или 'D.
    letter = строка

  • [widget name].get_order()
    Возвращает порядок УЦИ в виджете, который в основном используется для обеспечения их согласованности.
    Порядок также будет передан вместе с сигналом нажатия.
    Возвращает список, содержащий порядок.

  • [widget name].set_order(order)
    Устанавливает порядок УЦИ, в основном используется для поддержания их согласованности.
    order = объект списка, должен быть одним из:

    • ["Rel", "Abs", "DTG"] (по умолчанию)

    • ["DTG", "Rel", "Abs"]

    • ["Abs", "DTG", "Rel"]

  • [widget name].get_position()
    Возвращает позицию УЦИ в виде списка чисел с плавающей запятой.
    Порядок не зависит от отображаемого на УЦИ порядка, и будет задаваться следующим образом: [Absolute , relative , DTG].

    • Absolute = координаты станка , зависят от фактических свойств, дают фактическое или заданное положение.

    • Relative = будут координаты фактической системы координат.

    • DTG = расстояние, которое нужно пройти.
      Чаще всего будет 0, так как эту функцию не следует использовать во время движения станка из-за временных задержек..

Виджет будет выдавать следующие сигналы:

  • clicked
    Этот сигнал подается, когда пользователь нажимает на виджет Combi_DRO.
    Он отправит следующие данные:

    • widget = объект виджета
      Объект виджета, который выдает сигнал.

    • joint_number = integer
      Номер сочленения УЦИ, где 0:X 1:Y 2:Z и т.д.

    • order = объект списка
      Порядок УЦИ в этом виджете.
      Порядок можно использовать для установки других виджетов Combi_DRO в тот же порядок с помощью [widget name].set_order(order).

  • units_changed
    Этот сигнал выдается при смене единиц УЦИ.
    Он отправит следующие данные:

    • widget = объект виджета
      Объект виджета, который выдает сигнал.

    • metric_units = boolean
      True, если УЦИ отображает метрические единицы измерения, False в случае имперских..

  • system_changed
    Этот сигнал выдается при смене единиц УЦИ.
    Он отправит следующие данные:

    • widget = объект виджета
      Объект виджета, который выдает сигнал.

    • system = string
      Реальная система координат. Будет один из G54 G55 G56 G57 G58 G59 G59.1 G59.2 G59.3 или Rel, если ничего не выбрано вообще, что произойдет только в Glade без запуска LinuxCNC..

С помощью команд можно получить некоторую информацию, которая может вас заинтересовать:

  • [widget name].system
    Фактическая система, как указано в сигнале system_changed.

  • [widget name].homed
    True , если сочленение в исходной позиции.

  • [widget name].machine_units
    0, если имперская система мер, 1, если метрическая система мер.

images/combi_dro.png
Figure 15. Пример: три Combi_DRO в окне
X = Relative Mode
Y = Absolute Mode
Z = DTG Mode

6.23. IconView (Выбор файла)

Это удобный виджет с сенсорным экраном для выбора файла и изменения каталогов.

6.23.1. Свойства

IconView виджет имеет следующие свойства:

icon_size

Устанавливает размер отображаемого значка.
Допустимые значения — целые числа в диапазоне от 12 до 96.
По умолчанию — 48.

start_dir

Устанавливает каталог для запуска, когда виджет отобразится первый раз.
Должно быть строкой, содержащей действительный путь к каталогу.
По умолчанию — "/".

jump_to_dir

Устанавливает каталог "перехода", который выбирается соответствующей кнопкой в нижнем списке кнопок (5-я кнопка, считая слева).
Должно быть строкой, содержащей действительный путь к каталогу.
По умолчанию — "\~".

filetypes

Устанавливает файловый фильтр для отображаемых объектов.
Должно быть строкой, содержащей список отображаемых расширений, разделенных запятыми.
По умолчанию — "ngc,py".

sortorder

Устанавливает порядок сортировки отображаемого значка.
Должно быть целым числом от 0 до 3, где:

  • 0 = ASCENDING (отсортировано по именам файлов)

  • 1 = DESCENDING (отсортировано по именам файлов)

  • 2 = FOLDERFIRST (сначала показывать папки, потом файлы), по умолчанию

  • 3 = FILEFIRST (сначала показывать файлы, потом папки)

6.23.2. Прямое управление программой

Использование GObject для установки перечисленных выше свойств:

[widget name].set_property(property,Value)

Существуют методы Python для управления виджетом:

  • [widget name].show_buttonbox(state)
    Если в False, нижняя панель кнопок будет скрыта.
    Это полезно для пользовательских экранов со специальным расположением кнопок, позволяющим не изменять структуру ГИП. Хорошим примером является GMOCCAPY.
    state = boolean (True or False).
    По умолчанию — True.

  • [widget name].show_filelabel(state)
    Если принимает значение True, будет отображаться метка файла (между окном IconView и нижней панелью кнопок).
    Скрытие этой метки может сэкономить место, но ее отображение очень полезно для отладки.
    state = boolean (True or False).
    По умолчанию — True.

  • [widget name].set_icon_size(iconsize)
    Устанавливает размер иконки.
    Должно быть целое число в диапазоне от 12 до 96.
    По умолчанию = 48.

  • [widget name].set_directory(directory)
    Позволяет установить каталог для отображения.
    directory = string (a valid file path).

  • [widget name].set_filetypes(filetypes)
    Устанавливает используемый файловый фильтр.
    Будут показаны только файлы с указанными расширениями.
    filetypes = строка, содержащая список расширений, разделенных запятыми.
    По умолчанию = "ngc,py".

  • [widget name].get_selected()
    Возвращает путь к выбранному файлу или «None», если был выбран каталог.

  • [widget name].refresh_filelist()
    Обновляет список файлов.
    Нужен, если вы добавляете файл без изменения каталога.

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

[widget name].btn_home.emit("clicked")
[widget name].btn_jump_to.emit("clicked")
[widget name].btn_sel_prev.emit("clicked")
[widget name].btn_sel_next.emit("clicked")
[widget name].btn_get_selected.emit("clicked")
[widget name].btn_dir_up.emit("clicked")
[widget name].btn_exit.emit("clicked")

6.23.3. Сигналы

Виджет будет выдавать следующие сигналы:

  • selected
    Этот сигнал выдается, когда пользователь выбирает значок.
    Он вернет строку, содержащую путь к файлу, если был выбран файл или «None», если был выбран каталог.

  • sensitive
    Этот сигнал подается, когда кнопки меняют свое состояние с чувствительного на нечувствительное или наоборот.
    Этот сигнал полезен для синхронизации окружающего ГИП с кнопкой виджета. См. пример GMOCCAPY.
    Он вернет buttonname и новое state:

    • buttonname одно из btn_home, btn_dir_up, btn_sel_prev, btn_sel_next, btn_jump_to или btn_select.

    • state является логическим значением и будет иметь значение True или False.

  • exit
    Этот сигнал выдается при нажатии кнопки выхода для закрытия IconView.
    Чаще всего требуется, если приложение запускается автономно.

images/iconview.png
Figure 16. Пример Iconview

6.24. Виджет калькулятора

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

6.24.1. Свойства

`calculator`имеет следующие свойства:

is_editable

Это позволяет вводить ввод с клавиатуры.

font

Это позволяет вам установить шрифт дисплея.

6.24.2. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование goobject для установки перечисленных выше свойств:

[widget name].set_property("is_editable",True)
[widget name].set_property("font","sans 25")

Существуют методы Python:

  • [widget name].set_value(2.5)
    Предустанавливает дисплей и записывается.

  • [widget name].set_font("sans 25")

  • [widget name].set_editable(True)

  • [widget name].get_value()
    Возвращает вычисленное значение — число с плавающей запятой.

  • [widget name].set_editable(True)

  • [widget name].get_preset_value()
    Возвращает записанное значение: число с плавающей запятой.

6.25. Виджет редактора инструментов

Это виджет редактор инструментов для отображения и изменения файла инструмента.
В режиме токарного станка корректоры износа и коррекции инструмента будут отображаться отдельно.
Коррекции износа обозначаются номером инструмента выше 10000 (стиль Fanuc).
Он проверяет текущий файл раз в секунду, чтобы увидеть, обновил ли его LinuxCNC.

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

6.25.1. Свойства

tooleditor имеет следующие свойства:

font

Отобразить шрифт, который будет использоваться

hide_columns

Это скроет данные столбцы.
Столбцы обозначаются (по порядку) следующим образом: s,t,p,x,y,z,a,b,c,u,v,w,d,i,j,q.
Вы можете скрыть любое количество столбцов, включая выделение и комментарии.

lathe_display_type

Показать формат токарного станка

6.25.2. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование goobject для установки перечисленных выше свойств:

[widget name].set_properties('hide_columns','uvwijq')

Это скроет столбцы uvwij и q и отобразит все остальные.

Существуют методы Python:

  • [widget name].set_visible("ijq",False)
    Скрыло столбцы ij и Q, а остальные оставило как есть.

  • [widget name].set_filename(path_to_file)
    Устанавливает и загружает файл инструмента.

  • [widget name].reload(None)
    Перезагружает текущий файл инструмента.

  • [widget name].set_font('sans 16,tab='1')
    Устанавливает шрифт (Pango) на вкладке, заголовке столбца и данных инструмента.
    all_offsets, wear_offsets, tool_offsets можно установить одновременно, добавив 1, 2 и/или 3 к строке табуляции.
    По умолчанию установлены все вкладки.

  • [widget name].set_title_font('sans 16,tab='1')
    Устанавливает шрифт (Pango) только для заголовков столбцов.
    all_offsets, wear_offsets, tool_offsets можно установить одновременно, добавив 1, 2 и/или 3 к строке табуляции.
    По умолчанию установлены все вкладки.

  • [widget name].set_tab_font('sans 16,tab='1')
    Устанавливает шрифт (Pango) только на вкладках.
    all_offsets, wear_offsets, tool_offsets можно установить одновременно, добавив 1, 2 и/или 3 к строке табуляции.
    По умолчанию установлены все вкладки.

  • [widget name].set_col_visible("abcUVW", False, tab='1')
    Это скроет (False) столбцы abcuvw на вкладке 1 (all_offsets)

  • [widget name].set_lathe_display(value)
    Скрывает или показывает вкладки износа и коррекции инструмента, используемые на токарных станках.

  • [widget name].get_toolinfo(toolnum)
    Возвращает массив информации об инструменте с запрошенным номером инструмента или текущего инструмента, если номер инструмента не указан.
    Возвращает None, если инструмент не найден в таблице или текущий инструмент отсутствует.

  • [widget name].hide_buttonbox(self, True)
    Удобный метод скрытия кнопок.
    Вы должны вызвать это после show_all().

  • [widget name].get_selected_tool()
    Возвращает выбранный пользователем (выделенный) номер инструмента.

  • [widget name].set_selected_tool(toolnumber)
    Выбирает (подсвечивает) требуемый инструмент.

images/gtk-tooledit.png
Figure 17. Пример Tooleditor

6.26. Offsetpage

Виджет Offsetpage используется для отображения/редактирования смещений всех осей.
Он имеет удобные кнопки для обнуления смещений G92 и вращения вокруг оси Z.
Это позволит вам выбирать режим редактирования только тогда, когда станок включен и находится в режиме ожидания.
В это время вы можете напрямую редактировать смещения в таблице. Снимите флажок с кнопки редактирования, чтобы позволить OffsetPage отражать изменения.

6.26.1. Свойства

Он имеет следующие свойства:

display_units_mm

Отображение в метрических единицах

hide_columns

Список столбцов без пробелов, которые нужно скрыть. Столбцы обозначаются (по порядку) следующим образом: xyzabcuvwt.
Вы можете скрыть любой из столбцов.

hide_rows

Список строк без пробелов, которые нужно скрыть.
Строки обозначаются (по порядку) так: 0123456789abc.
Вы можете скрыть любую из строк.

font

Устанавливает тип и размер шрифта текста.

highlight_color

При редактировании это цвет выделения.

foreground_color

Когда OffsetPage обнаруживает активную пользовательскую систему координат, он будет использовать этот цвет для текста.

mm_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.

imperial_text_template

Вы можете использовать форматирование Python для отображения позиции с разной точностью.

6.26.2. Прямое управление программой

Существует несколько способов прямого управления виджетом с помощью Python.

Использование goobject для установки перечисленных выше свойств:

[widget name].set_property("highlight_color",gdk.Color('blue'))
[widget name].set_property("foreground_color",gdk.Color('black'))
[widget name].set_property("hide_columns","xyzabcuvwt")
[widget name].set_property("hide_rows","123456789abc")
[widget name].set_property("font","sans 25")

Существуют методы Python для управления виджетом:

  • [widget name].set_filename("../../../configs/sim/gscreen/gscreen_custom/sim.var")

  • [widget name].set_col_visible("Yabuvw",False)

  • [widget name].set_row_visible("456789abc",False)

  • [widget name].set_to_mm()

  • [widget name].set_to_inch()

  • [widget name].hide_button_box(True)

  • [widget name].set_font("sans 20")

  • [widget name].set_highlight_color("violet")

  • [widget name].set_foreground_color("yellow")

  • [widget name].mark_active("G55")
    Позволяет напрямую указать строку для выделения, например, если вы хотите использовать собственные элементы управления навигацией. См. главу GMOCCAPY.

  • [widget name].selection_mask = ("Tool","Rot","G5x")
    Эти строки НЕ доступны для выбора в режиме редактирования.

  • [widget name].set_names([['G54','Default'],["G55","Vice1"],['Rot','Rotational']])
    Это позволяет вам установить текст столбца T каждой/любой строки.
    Это список пар offset-name/user-name.
    Текст по умолчанию тот же, что и имя смещения.

  • [widget name].get_names()
    Это возвращает список пар row-keyword/user-name.
    Столбец имени пользователя доступен для редактирования, поэтому сохранение этого списка удобно для пользователя.
    См. set_names выше.

images/offsetpage.png
Figure 18. Пример Offsetpage

6.27. Виджет HAL_sourceview

Это для отображения и простого редактирования G-кода. Он ищет спецификации подсветки .ngc в ~/share/gtksourceview-2.0/language-specs/. Текущая бегущая строка будет выделена.

С помощью внешнего связующего кода Python он может:

  • Поиск текста, отмена и повтор изменений.

  • Используется для выбора строки программы.

6.27.1. Прямое управление программой

Существуют методы Python для управления виджетом:

  • [widget name].redo()
    Повторить один уровень изменений.

  • [widget name].undo()
    Отменить один уровень изменений

  • [widget name].text_search(direction=True,mixed_case=True,text='G92')
    Поиск вперед (направление = True) или назад,
    Поиск со смешанным регистром (mixed_case = True) или с точным совпадением

  • [widget name].set_line_number(linenumber)
    Устанавливает линию для выделения.
    Использует номера строк исходного кода.

  • [widget name].get_line_number()
    Возвращает текущую выделенную строку.

  • [widget name].line_up()
    Перемещает выделенную строку на одну строку вверх.

  • [widget name].line_down()
    Перемещает выделенную строку на одну строку вниз.

  • [widget name].load_file('filename')
    Загружает файл.
    Использование None (не строки имени файла) приведет к перезагрузке той же программы.

  • [widget name].get_filename()
    FIXME описание

images/hal_sourceview.png
Figure 19. Пример Sourceview

6.28. История MDI

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

6.28.1. Свойства

font_size_tree

Целое значение от 8 до 96.
Изменит размер шрифта по умолчанию для древовидного представления на выбранное значение.

font_size_entry

Целое значение от 8 до 96.
Измените размер шрифта записи по умолчанию на выбранное значение.

use_double_click

Boolean, True включает функцию двойного щелчка мышью, а двойной щелчок по записи отправляет эту команду.
Не рекомендуется использовать эту функцию на реальных станках, поскольку двойной щелчок по неправильной записи может привести к опасным ситуациям.

6.28.2. Прямое управление программой

Использование goobject для установки перечисленных выше свойств:

[widget name].set_property("font_size_tree",10)
[widget name].set_property("font_size_entry",20)
[widget name].set_property("use_double_click",False)

6.29. Анимированные функциональные диаграммы: виджеты HAL в растровом изображении

Для некоторых приложений может быть желательно иметь фоновое изображение (например, функциональную диаграмму) и размещать виджеты в соответствующих местах этого изображения. Хорошей комбинацией является установка растрового фонового изображения, например, из файла .png, создание фиксированного размера окна GladeVCP и использование виджета Glade фиксированного для размещения виджетов на этом изображении. Код приведенного ниже примера можно найти в configs/apps/gladevcp/animated-backdrop:

images/small-screenshot.png
Figure 20. Пример виджеты HAL в растровом изображении

7. Справочник по виджетам действий

GladeVCP включает в себя набор "стандартных действий" под названием VCP Action Widgets для редактора пользовательского интерфейса Glade.

Note

Помимо виджетов HAL, которые взаимодействуют с контактами HAL, действия VCP взаимодействуют с LinuxCNC и интерпретатором G-кода.

Виджеты действий VCP являются производными от виджета Gtk.Action.

Коротко о виджете Action:

  • Это объект, доступный в Glade

  • Сам по себе он не имеет внешнего вида

  • Его цель: связать видимый, чувствительный компонент пользовательского интерфейса, такой как меню, кнопка инструмента или кнопка, с командой. См. свойство General→Related→Action этого виджета.

  • "Стандартное действие" будет выполняться при запуске соответствующего компонента пользовательского интерфейса (нажатие кнопки, щелчок меню…).

  • Он обеспечивает простой способ выполнения команд, не прибегая к программированию на Python.

Внешний вид VCP Actions в Glade примерно следующий:

images/vcp-actions.png
Figure 21. Виджеты Action

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

7.1. Виджеты VCP Action

Виджеты действий VCP — это виджеты одноразового типа. Они реализуют одно действие и предназначены для использования в простых кнопках, пунктах меню или группах переключателей/проверок.

7.2. VCP Action Python

Этот виджет используется для выполнения небольшого произвольного кода Python.

В командной строке могут использоваться специальные ключевые слова для доступа к важным функциям.

  • ACTION для доступа к библиотеке команд ACTION.

  • GSTAT для доступа к библиотеке статусных сообщений Gstat.

  • INFO для доступа к собранным данным из INI-файла.

  • HAL для доступа к модулю HAL linuxcnc Python

  • STAT для доступа к исходному статусу LinuxCNC через модуль LinuxCNC Python.

  • CMD для доступа к командам LinuxCNC через модуль LinuxCNC Python.

  • EXT для доступа к функциям файла-обработчика, если они доступны.

  • linuxcnc для доступа к модулю LinuxCNC Python.

  • self для доступа к экземпляру виджета.

  • dir для доступа к списку атрибутов обработчиков.

Есть варианты

  • выбрать, когда виджет будет активен,

  • установить режим перед выполнением команды.

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

print('action activated')

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

CMD.state(linuxcnc.STATE_OFF)

Пример команды для вызова функции-обработчика, передающей данные:

EXT.on_button_press(self, 100)

Вы можете использовать точку с запятой для разделения нескольких команд;

print('Set Machine Off');CMD.state(linuxcnc.STATE_OFF)

Более подробную информацию о INFO и ACTION можно найти здесь: GladeVCP Libraries modules.

Более подробную информацию о GStat можно найти здесь.: GStat.

7.3. Виджеты VCP ToggleAction

Это бимодальные виджеты. Они реализуют два действия или используют второе (обычно нажатое) состояние, чтобы указать, что в данный момент выполняется действие. Действия переключения предназначены для использования в ToggleButtons, ToggleToolButtons или для переключения пунктов меню. Симплексным примером является кнопка переключения ESTOP.

На данный момент доступны следующие виджеты:

  • Переключатель ESTOP отправляет команды ESTOP или ESTOP_RESET в LinuxCNC в зависимости от его состояния.

  • Переключатель ON/OFF отправляет команды STATE_ON и STATE_OFF.

  • Pause/Resume отправляет команды AUTO_PAUSE или AUTO_RESUME.

Следующие действия переключения имеют только одну связанную команду и используют состояние pressed, чтобы указать, что запрошенная операция выполняется:

  • Переключатель Run отправляет команду AUTO_RUN и ждет в pressed состоянии, пока интерпретатор снова не перейдет в режим ожидания.

  • Переключение Stop неактивно до тех пор, пока интерпретатор не перейдет в активное состояние (выполняет G-код), а затем позволит пользователю отправить команду AUTO_ABORT.

  • Переключение MDI отправляет заданную команду MDI и ожидает ее завершения в pressed неактивном состоянии.

7.4. Виджеты Action_MDI Toggle и Action_MDI

Эти виджеты предоставляют средства для выполнения произвольных команд MDI.
Виджет Action_MDI не ожидает завершения команды, как это делает переключатель Action_MDI, который остается отключенным до завершения команды.

7.5. Простой пример: выполнение команды MDI при нажатии кнопки

configs/apps/gladevcp/mdi-command-example/whoareyou.ui — это файл пользовательского интерфейса Glade, который передает основы:

  1. Откройте его в Glade и изучите, как это делается.

  2. Запустите AXIS, а затем запустите его из окна терминала с помощью gladevcp whoareyou.ui.

  3. См. действие hal_action_mdi1 и его свойство MDI command — оно просто выполняет (MSG, "Hi, I'm an VCP_Action_MDI"), поэтому в AXIS должно появиться всплывающее окно с сообщением, например:

images/whoareyou.png
Figure 22. Простой пример Action_MDI

Вы заметите, что кнопка, связанная с действием Action_MDI, неактивна, если машина выключена, находится в режиме аварийного останова или если интерпретатор работает. Он автоматически становится активным, когда станок включается и выходит из режима аварийного останова, а программа находится в режиме ожидания.

7.6. Передача параметров с помощью виджетов Action_MDI и ToggleAction_MDI

При желании в строки MDI-команды могут быть подставлены параметры перед их передачей интерпретатору. В настоящее время параметрами могут быть имена контактов HAL в компоненте GladeVCP. Вот как это работает:

  • Предположим, у вас есть HAL SpinBox с именем speed, и вы хотите передать его текущее значение в качестве параметра в команде MDI.

  • HAL SpinBox будет иметь контакт HAL плавающего типа с именем Speed-f (см. описание HalWidgets).

  • Чтобы заменить это значение в команде MDI, вставьте имя контакта HAL, заключенное следующим образом: ${pin-name}

  • для приведенного выше HAL SpinBox мы могли бы использовать (MSG, "The speed is: ${speed-f}") просто для того, чтобы показать, что происходит.

Пример файла пользовательского интерфейса — configs/apps/gladevcp/mdi-command-example/speed.ui. Вот что вы получите при его запуске:

images/speed.png
Figure 23. Пример передачи параметра Action_MDI

7.7. Расширенный пример: передача параметров в подпрограмму с О-словом

Совершенно нормально вызывать подпрограмму с O-словом в команде MDI и передавать значения контактов HAL в качестве фактических параметров. Пример файла пользовательского интерфейса находится в configs/apps/gladevcp/mdi-command-example/owordsub.ui.

Поместите nc_files/gladevcp_lib/oword.ngc, чтобы AXIS могла его найти, и запустите gladevcp owordsub.ui из окна терминала. Это выглядит так:

images/oword.png
Figure 24. Расширенный пример Action_MDI

7.8. Подготовка к действию MDI и последующая очистка

Интерпретатор G-кода LinuxCNC имеет единый глобальный набор переменных, таких как подача, скорость шпинделя, относительный/абсолютный режим и другие. Если вы используете команды G-кода или подпрограммы O-слов, некоторые из этих переменных могут быть изменены командой или подпрограммой - например, процедура проверки, скорее всего, установит значение подачи довольно низким. Без каких-либо дополнительных мер предосторожности ваша предыдущая настройка подачи будет перезаписана значением подпрограммы зондирования.

Чтобы справиться с этим удивительным и нежелательным побочным эффектом данной подпрограммы O-слова или оператора G-кода, выполняемого с помощью LinuxCNC ToggleAction_MDI, вы можете связать обработчики до и после MDI с данным LinuxCNC ToggleAction_MDI. Эти обработчики являются необязательными и предоставляют возможность сохранить любое состояние перед выполнением действия MDI, а затем восстановить его до предыдущих значений. Имена сигналов: mdi-command-start и mdi-command-stop; имена обработчиков могут быть установлены в Glade, как и в любом другом обработчике.

Вот пример того, как значение канала может быть сохранено и восстановлено такими обработчиками (обратите внимание, что каналы команд и состояния LinuxCNC доступны как self.linuxcnc и self.stat через класс VCP_ActionBase):

    def on_mdi_command_start(self, action, userdata=None):
        action.stat.poll()
        self.start_feed = action.stat.settings[1]

    def on_mdi_command_stop(self, action, userdata=None):
        action.linuxcnc.mdi('F%.1f' % (self.start_feed))
        while action.linuxcnc.wait_complete() == -1:
            pass

Только виджет Action_MDI Toggle поддерживает эти сигналы.

Note

В более поздней версии LinuxCNC будут доступны новые M-коды M70-M72. Они значительно упростят сохранение состояния перед вызовом подпрограммы и восстановление состояния при возврате.

7.9. Использование объекта LinuxCNC Stat для обработки изменений статуса

Многие действия зависят от статуса LinuxCNC — в ручном, MDI или автоматическом режиме? Программа запущена, приостановлена или простаивает? Вы не можете запустить команду MDI во время работы программы G-кода, поэтому об этом необходимо позаботиться. Многие действия LinuxCNC заботятся об этом сами, а соответствующие кнопки и пункты меню деактивируются, когда операция в данный момент невозможна.

При использовании обработчиков событий Python, которые находятся на более низком уровне, чем Actions, необходимо самому позаботиться о работе с зависимостями состояния. Для этой цели существует виджет LinuxCNC Stat: для связи изменений состояния LinuxCNC с обработчиками событий.

LinuxCNC Stat не имеет видимого компонента — вы просто добавляете его в свой пользовательский интерфейс с помощью Glade. После добавления вы можете связать обработчики со следующими сигналами:

  • связанные с состоянием:

    • state-estop: выдается при возникновении состояния аварийного останова,

    • state-estop-reset: выдается при сбросе станка,

    • state-on: выдается при включении станка,

    • state-off: выдается, когда станок выключен.

  • связанные с режимом:

    • mode-manual: выдается, когда LinuxCNC переходит в ручной режим,

    • mode-mdi: выдается, когда LinuxCNC входит в режим MDI,

    • mode-auto: выдается, когда LinuxCNC переходит в автоматический режим,

  • связанный с интерпретатором: генерируется, когда интерпретатор G-кода переходит в этот режим

    • interp-run

    • interp-idle

    • interp-paused

    • interp-reading

    • interp-waiting

    • file-loaded

    • line-changed

  • связанный с исходным положением: генерируется, когда LinuxCNC в исходном состоянии или нет

    • all-homed

    • not-all-homed

8. Программирование GladeVCP

8.1. Действия, определяемые пользователем

Большинство наборов виджетов и связанные с ними редакторы пользовательского интерфейса поддерживают концепцию обратных вызовов, то есть функций в написанном пользователем коде, которые выполняются, когда что-то происходит в пользовательском интерфейсе — такие события, как щелчки мыши, ввод символов, движение мыши, события таймера и т. д. скрытие и экспозиция окон и так далее.

Виджеты вывода HAL обычно сопоставляют события типа ввода, такие как нажатие кнопки, с изменением значения связанного контакта HAL посредством такого заранее определенного обратного вызова. В PyVCP это действительно единственный поддерживаемый тип обработки событий — выполнение чего-то более сложного, например выполнение команд MDI для вызова подпрограммы G-кода, не поддерживается.

В GladeVCP изменения контактов HAL — это всего лишь один тип общего класса событий (называемых сигналами) в GTK+. Большинство виджетов могут генерировать такие сигналы, и редактор Glade поддерживает связывание такого сигнала с именем метода или функции Python.

Если вы решите использовать пользовательские действия, ваша задача — написать модуль Python, методы класса которого — или, в простом случае, просто функции — могут называться в Glade обработчиками событий. GladeVCP предоставляет возможность импортировать ваши модули при запуске и автоматически связывает ваши обработчики событий с сигналами виджетов, как указано в описании пользовательского интерфейса Glade.

8.2. Основная библиотека

Существует три библиотеки функций, которые можно использовать для программирования GladeVCP.

  • Info: собирает данные из INI-файла.

  • Action: Набор функций для изменения состояний LinuxCNC.

  • Status: Сообщает о состоянии LinuxCNC. Он окружает Gstat.

Импорт и создание экземпляров библиотек:

from gladevcp.core import Info, Action

ACTION = Action()
INFO = Info()

Использование функций библиотеки:

print(INFO.MACHINE_IS_METRIC)
ACTION.SET_ERROR_MESSAGE('Something went wrong')

Дополнительную информацию можно найти здесь: GladeVCP Libraries modules. Существует пример конфигурации, демонстрирующий использование базовой библиотеки с виджетами Python действий GladeVCP и файлом-обработчиком Python. Попробуйте загрузить sim/axis/gladevcp/gladevcp_panel_tester.

8.3. Пример: добавление пользовательских обратных вызовов в Python

Это всего лишь минимальный пример, передающий идею — подробности изложены в оставшейся части этого раздела.

GladeVCP может не только манипулировать или отображать контакты HAL, вы также можете писать обычные обработчики событий на Python. Это можно использовать, среди прочего, для выполнения команд MDI. Вот как это сделать:

Напишите такой модуль Python и сохраните его, например: handlers.py:

nhits = 0
def on_button_press(gtkobj,data=None):
    global nhits
    nhits += 1
    gtkobj.set_label("hits: %d" % nhits)

В Glade определите кнопку или HAL кнопку, выберите вкладку Signals, а в свойствах GtkButton выберите строку pressed. Введите туда on_button_press и сохраните файл Glade.

Затем добавьте опцию -u handlers.py в командную строку GladeVCP. Если ваши обработчики событий распределены по нескольким файлам, просто добавьте несколько опций -u <pyfilename>.

Теперь нажатие кнопки должно изменить ее метку, поскольку она установлена в функции обратного вызова.

Что делает флаг +-u+: все функции Python в этом файле собираются и настраиваются как потенциальные обработчики обратного вызова для ваших виджетов Gtk — на них можно ссылаться на вкладках Glade Signals. Обработчики обратного вызова вызываются с конкретным экземпляром объекта в качестве параметра, как и экземпляр GtkButton выше, поэтому вы можете применить оттуда любой метод GtkButton.

Или сделайте еще что-нибудь полезное, например вызов команды MDI!

8.4. События изменения значения HAL

Виджеты ввода HAL, такие как светодиод, автоматически связывают состояние своего контакта HAL (включено/выключено) с оптическим внешним видом виджета (светодиод горит/погашен).

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

Для определяемых пользователем контактов HAL, не связанных с конкретным виджетом HAL, имя сигнала имеет значение value-changed. Подробности см. в разделе Добавление контактов HAL ниже.

Виджеты HAL идут с заранее определенным сигналом, который называется hal-pin-changed. Подробности смотрите в разделе HAL Widgets.

8.5. Модель программирования

Общий подход заключается в следующем:

  • Создайте свой пользовательский интерфейс с помощью Glade и установите обработчики сигналов там, где вы хотите, чтобы действия были связаны с виджетом.

  • Напишите модуль Python, содержащий вызываемые объекты (см. handler models ниже).

  • Передайте путь к вашему модулю в GladeVCP с помощью опции -u <module>.

  • GladeVCP импортирует модуль, проверяет его на наличие обработчиков сигналов и подключает их к дереву виджетов.

  • Запускается основной цикл событий.

8.5.1. Простая модель обработчика

Для простых задач достаточно определить функции, названные в честь обработчиков сигналов Glade. Они будут вызываться, когда в дереве виджетов произойдет соответствующее событие. Вот тривиальный пример: предполагается, что сигнал pressed кнопки Gtk или кнопки HAL связан с обратным вызовом под названием on_button_press:

nhits = 0
def on_button_press(gtkobj,data=None):
    global nhits
    nhits += 1
    gtkobj.set_label("hits: %d" % nhits)

Добавьте эту функцию в файл Python и запустите следующим образом:

gladevcp -u <myhandler>.py mygui.ui

Обратите внимание, что связь между обработчиками должна осуществляться через глобальные переменные, что плохо масштабируется и явно не питонично. Вот почему мы придумали модель обработчика на основе классов.

8.5.2. Модель обработчика на основе классов

Идея здесь такова: обработчики связаны с методами класса. Базовые классы создаются и проверяются во время запуска GladeVCP и связываются с деревом виджетов в качестве обработчиков сигналов. Итак, задача теперь состоит в том, чтобы написать:

  • Одно или несколько определений классов с одним или несколькими методами, в одном модуле или разделенные на несколько модулей,

  • функция get_handlers в каждом модуле, которая будет возвращать список экземпляров классов в GladeVCP — имена их методов будут связаны с обработчиками сигналов.

Вот минимальный пример модуля определяемого пользователем обработчика:

class MyCallbacks :
    def on_this_signal(self,obj,data=None):
        print("this_signal happened, obj=",obj)

def get_handlers(halcomp,builder,useropts):
    return [MyCallbacks ()]

Теперь on_this_signal будет доступен в качестве обработчика сигнала для вашего дерева виджетов.

8.5.3. Сигналы, специфичные для GladeVCP

Для панели GladeVCP, которая реагирует на входы HAL, может быть важно, чтобы код обработчика мог сообщать, что панель GladeVCP в данный момент активна и отображается. Например, панели внутри интерфейса Touchy вполне может потребоваться выполнить действие при срабатывании переключателя, подключенного к touchy.cycle-start (точно так же, как собственные вкладки по-разному реагируют на одну и ту же кнопку).
Чтобы это стало возможным, из ГИП (на момент написания статьи только Touchy) отправляется сигнал на встроенную вкладку. Сигнал имеет тип "Gladevcp", и отправляются два сообщения: "Visible" и "Hidden". (Обратите внимание, что сигналы имеют фиксированную длину в 20 символов, поэтому при любом сравнении следует использовать только первые символы, отсюда и [:7] ниже.) Пример обработчика для этих сигналов:

    # This catches our messages from another program
    def event(self,w,event):
        print(event.message_type,event.data)
        if event.message_type == 'Gladevcp':
            if event.data[:7] == 'Visible':
                self.active = True
            else:
                self.active = False

    # connect to client-events from the host GUI
    def on_map_event(self, widget, data=None):
        top = widget.get_toplevel()
        print("map event")
        top.connect('client-event', self.event)

8.5.4. Протокол get_handlers

Если во время проверки модуля GladeVCP обнаруживает функцию get_handlers, она вызывает ее следующим образом:

get_handlers(halcomp,builder,useropts)

Аргументы:

  • halcomp - относится к разрабатываемому компоненту HAL,

  • builder - дерево виджетов — результат чтения определения пользовательского интерфейса (либо ссылка на объект типа GtkBuilder, либо на объект типа libglade),

  • useropts - список строк, собранных из опции командной строки GladeVCP -U <useropts>.

Затем GladeVCP проверяет список экземпляров классов и извлекает имена их методов. Имена уточняющих методов подключаются к дереву виджетов как обработчики сигналов. Учитываются только имена методов, которые не начинаются с символа _ (подчеркивание).

Обратите внимание: независимо от того, используете ли вы libglade или новый формат GtkBuilder для своего пользовательского интерфейса Glade, виджеты всегда можно называть builder.get_object(<widgetname>). Кроме того, полный список виджетов доступен как builder.get_objects() независимо от формата пользовательского интерфейса.

8.6. Последовательность инициализации

Важно знать, в каком случае вызывается ваша функция get_handlers(), чтобы вы знали, что там делать безопасно, а что нет. Сначала модули импортируются и инициализируются в порядке командной строки. После успешного импорта get_handlers() вызывается в следующем состоянии:

  • Дерево виджетов создано, но еще не реализовано (еще не выполнено window.show() верхнего уровня).

  • Компонент halcomp HAL настроен, и к нему уже добавлены контакты всех виджетов HAL.

  • Добавлять больше контаков HAL безопасно, поскольку на этом этапе halcomp.ready() еще не вызывался, поэтому вы можете добавить свои собственные выводы, например, в методе класса init()`.

После того как все модули импортированы и имена методов извлечены, выполняются следующие шаги:

  • Все имена соответствующих методов будут подключены к дереву виджетов с помощью connect_signals()/signal_autoconnect() (в зависимости от типа импортируемого пользовательского интерфейса — GtkBuilder или старый формат libglade).

  • Компонент HAL завершается с помощью halcomp.ready().

  • Если ID окна был передан в качестве аргумента, дерево виджетов перестраивается для запуска в этом окне, а window1 верхнего уровня Glade1 закрывается (см. FAQ).

  • Если командный файл HAL был передан с параметром -H halfile, он выполняется с помощью halcmd.

  • Запускается основной цикл Gtk.

Поэтому, когда ваш класс-обработчик инициализирован, все виджеты существуют, но еще не реализованы (отображаются на экране). Компонент HAL также не готов, поэтому небезопасно получать доступ к значениям контактов в вашем методе __init__().

Если вы хотите, чтобы обратный вызов выполнялся при запуске программы после того, как доступ к выводам HAL станет безопасным, тогда подключите обработчик к сигналу реализации window1 верхнего уровня (что может быть его единственной реальной целью). На этом этапе GladeVCP завершил все задачи настройки, файл HAL запущен, и GladeVCP собирается войти в основной цикл Gtk.

8.7. Несколько обратных вызовов с одним и тем же именем

Внутри класса имена методов должны быть уникальными. Однако вполне нормально иметь несколько экземпляров класса, передаваемых в GladeVCP с помощью get_handlers() с одинаковыми именами методов. При возникновении соответствующего сигнала эти методы будут вызываться в порядке определения — модуль за модулем, а внутри модуля экземпляры класса возвращаются методом get_handlers().

8.8. Флаг GladeVCP -U <useropts>

Вместо расширения GladeVCP для любой мыслимой опции, которая потенциально может быть полезна для класса-обработчика, вы можете использовать флаг -U <useroption> (при желании несколько раз). Этот флаг собирает список строк <useroption>. Этот список передается в функцию get_handlers() (аргумент useropts). Ваш код может интерпретировать эти строки по своему усмотрению. Возможное использование — передать их функции exec Python в вашем get_handlers() следующим образом:

debug = 0
...
def get_handlers(halcomp,builder,useropts):
    ...
    global debug # assuming there's a global var
    for cmd in useropts:
        exec cmd in globals()

Таким образом, вы можете передавать в модуль произвольные операторы Python с помощью опции gladevcp -U, например:

gladevcp -U debug=42 -U "print 'debug=%d' % debug" ...

Это должно установить debug на 2 и подтвердить, что ваш модуль действительно это сделал.

8.9. Постоянные переменные в GladeVCP

Раздражающим аспектом GladeVCP в его более ранней форме и PyVCP является тот факт, что вы можете изменять значения и контакты HAL с помощью ввода текста, ползунков, полей прокрутки, кнопок переключения и т. д., но их настройки не сохраняются и не восстанавливаются при следующем запуске LinuxCNC — они начинаются со значения по умолчанию, установленного в определении панели или виджета.

GladeVCP имеет простой в использовании механизм для сохранения и восстановления состояния виджетов HAL и программных переменных (фактически любого атрибута экземпляра типа int, float, bool или string).

Этот механизм использует популярный формат файлов INI для сохранения и перезагрузки постоянных атрибутов.

Сохраняемость, версии программ и проверка подписи

Представьте себе переименование, добавление или удаление виджетов в Glade: файл .INI, хранящийся в предыдущей версии программы, или совершенно другой пользовательский интерфейс не смогут правильно восстановить состояние, поскольку переменные и типы могут измениться.

GladeVCP обнаруживает эту ситуацию по сигнатуре, которая зависит от всех имен и типов объектов, которые сохраняются и подлежат восстановлению. В случае несовпадения подписи создается новый INI-файл с настройками по умолчанию.

8.10. Использование постоянных переменных

Если вы хотите, чтобы какое-либо состояние виджета Gtk, выходные значения контактов виджетов HAL и/или атрибуты класса вашего класса-обработчика сохранялись при вызовах, действуйте следующим образом:

  • Импортируйте модуль Gladevcp.persistence.

  • Решите, какие атрибуты экземпляра и их значения по умолчанию вы хотите сохранить, если таковые имеются.

  • Решите, состояние каких виджетов должно сохраняться.

  • Опишите эти решения в методе \__init()__ вашего класса-обработчика через вложенный словарь следующим образом:

def __init__(self, halcomp,builder,useropts):
    self.halcomp = halcomp
    self.builder = builder
    self.useropts = useropts
    self.defaults = {
        # the following names will be saved/restored as method attributes
        # the save/restore mechanism is strongly typed - the variables type will be derived from the type of the
        # initialization value. Currently supported types are: int, float, bool, string
        IniFile.vars : { 'nhits' : 0, 'a': 1.67, 'd': True ,'c' : "a string"},
        # to save/restore all widget's state which might remotely make sense, add this:
        IniFile.widgets : widget_defaults(builder.get_objects())
        # a sensible alternative might be to retain only all HAL output widgets' state:
        # IniFile.widgets: widget_defaults(select_widgets(self.builder.get_objects(), hal_only=True,output_only = True)),
    }

Затем свяжите INI-файл с этим дескриптором:

self.ini_filename = __name__ + '.ini'
self.ini = IniFile(self.ini_filename,self.defaults,self.builder)
self.ini.restore_state(self)

После restore_state() у self будут установлены атрибуты, если выполняется следующее:

self.nhits = 0
self.a = 1.67
self.d = True
self.c = "a string"

Обратите внимание, что типы сохраняются и сохраняются при восстановлении. В этом примере предполагается, что файл INI не существует или имеет значения по умолчанию из self.defaults.

После этого заклинания вы можете использовать следующие методы IniFile:

ini.save_state(obj)

Сохраняет атрибуты objs согласно словарю IniFile.vars и состояние виджета, как описано в IniFile.widgets в self.defaults.

ini.create_default_ini()

Создает INI-файл со значениями по умолчанию.

ini.restore_state(obj)

Восстановите выходные контакты HAL и атрибуты объекта как сохраненные/инициализированные по умолчанию, как указано выше.

8.11. Сохранение состояния при завершении работы GladeVCP

Чтобы сохранить состояние виджета и/или переменной при выходе, выполните следующие действия:

  • Выберите какой-нибудь внутренний виджет (тип не важен, например стол).

  • На вкладке Signals выберите GtkObject. В первом столбце должен появиться сигнал destroy.

  • Добавьте имя обработчика, например. on_destroy во второй столбец.

  • Добавьте обработчик Python, как показано ниже:

import gtk
...
def on_destroy(self,obj,data=None):
    self.ini.save_state(self)

Это позволит сохранить состояние и правильно завершить работу GladeVCP, независимо от того, встроена ли панель в AXIS или является отдельным окном.

Caution

Не используйте window1 (окно верхнего уровня) для подключения события destroy. Из-за того, как панель GladeVCP взаимодействует с AXIS, если панель встроена в AXIS, window1 не будет правильно получать события уничтожения. Однако, поскольку при выключении все виджеты уничтожаются, подойдет любой. Рекомендуется: используйте виджет второго уровня — например, если у вас на панели есть контейнер таблицы, используйте его.

При следующем запуске приложения GladeVCP виджеты должны появиться в том состоянии, в котором оно было закрыто.

Caution

Строка GtkWidget имеет похожее звучание destroy-eventне используйте его для подключения к обработчику on_destroy, это не сработает — убедитесь, что вы используете событие «destroy из строки GtkObject.

8.12. Сохранение состояния при нажатии Ctrl-C

По умолчанию реакция GladeVCP на событие Ctrl-C заключается в простом выходе - без сохранения состояния. Чтобы убедиться, что этот случай рассмотрен, добавьте вызов обработчика on_unix_signal, который будет автоматически вызываться по Ctrl-C (фактически по сигналам SIGINT и SIGTERM). Пример:

def on_unix_signal(self,signum,stack_frame):
    print("on_unix_signal(): signal %d received, saving state" % (signum))
    self.ini.save_state(self)

8.13. Ручное редактирование файлов INI (.ini)

Вы можете это сделать, но учтите, что значения в self.defaults переопределяют ваши изменения, если в вашем редактировании есть синтаксическая или типическая ошибка. Ошибка обнаружена, консольное сообщение уведомит об этом, а плохой ini-файл будет переименован и получит суффикс .BAD. Последующие неверные файлы INI перезаписывают более ранние файлы .BAD.

8.14. Добавление контактов HAL

Если вам нужны контакты HAL, которые не связаны с конкретным виджетом HAL, добавьте их следующим образом:

import hal_glib
...
# in your handler class __init__():
self.example_trigger = hal_glib.GPin(halcomp.newpin('example-trigger', hal.HAL_BIT, hal.HAL_IN))

Чтобы получить обратный вызов при изменении значения этого контакта, свяжите обратный вызов value-change с этим контактом, добавьте:

self.example_trigger.connect('value-changed', self._on_example_trigger_change)

и определите метод обратного вызова (или функцию, в данном случае оставьте параметр self):

# note '_' - this method will not be visible to the widget tree
def _on_example_trigger_change(self,pin,userdata=None):
    print("pin value changed to:" % (pin.get()))

8.15. Добавление таймеров

Поскольку GladeVCP использует виджеты Gtk, основанные на базовом классе PyGObject, функционально доступен полный функционал GLib. Вот пример обратного вызова таймера:

def _on_timer_tick(self,userdata=None):
    ...
    return True # to restart the timer; return False for on-shot
...
# demonstrate a slow background timer - granularity is one second
# for a faster timer (granularity 100 ms), use this:
# GLib.timeout_add(100, self._on_timer_tick,userdata) # 10Hz
GLib.timeout_add_seconds(1, self._on_timer_tick)

8.16. Программная настройка свойств виджета HAL

В Glade свойства виджетов обычно устанавливаются фиксированными во время редактирования. Однако вы можете установить свойства виджета во время выполнения, например, из значений INI-файла, что обычно делается в коде инициализации обработчика. Также возможна установка свойств из значений контактов HAL.

В следующем примере (предполагается, что виджет HAL Meter называется meter) минимальное значение счетчика устанавливается из параметра INI-файла при запуске, а максимальное значение устанавливается через контакт HAL, что приводит к динамической перенастройке масштаба виджета:

import linuxcnc
import os
import hal
import hal_glib

class HandlerClass:

    def _on_max_value_change(self,hal_pin,data=None):
        self.meter.max = float(hal_pin.get())
        self.meter.queue_draw() # force a widget redraw

    def __init__(self, halcomp,builder,useropts):
        self.builder = builder

        # HAL pin with change callback.
        # When the pin's value changes the callback is executed.
        self.max_value = hal_glib.GPin(halcomp.newpin('max-value',  hal.HAL_FLOAT, hal.HAL_IN))
        self.max_value.connect('value-changed', self._on_max_value_change)

        inifile = linuxcnc.ini(os.getenv("INI_FILE_NAME"))
        mmin = float(inifile.find("METER", "MIN") or 0.0)
        self.meter = self.builder.get_object('meter')
        self.meter.min = mmin


def get_handlers(halcomp,builder,useropts):
    return [HandlerClass(halcomp,builder,useropts)]

8.17. Обратный вызов с изменением значения с помощью hal_glib

GladeVCP использует библиотеку hal_glib, которую можно использовать для подключения сигнала "watcher" к входному контакту HAL.
Этот сигнал можно использовать для регистрации функции, которая будет вызываться, когда вывод HAL меняет состояние.

Необходимо импортировать модули hal_glib и hal:

import hal_glib
import hal

Затем сделайте вывод и подключите сигнал value-changed (watcher) к вызову функции:

class HandlerClass:
    def __init__(self, halcomp,builder,useropts):
        self.example_trigger = hal_glib.GPin(halcomp.newpin('example-trigger', hal.HAL_BIT, hal.HAL_IN))
        self.example_trigger.connect('value-changed', self._on_example_trigger_change)

И есть функция, которую нужно вызвать:

    def _on_example_trigger_change(self,pin,userdata=None):
        print("pin value changed to: {}".format(pin.get()))
        print("pin name= {}".format(pin.get_name()))
        print("pin type= {}".format(pin.get_type()))

        # this can be called outside the function
        self.example_trigger.get()

8.18. Примеры и создание собственного приложения GladeVCP

Посетите linuxcnc_root_directory/configs/apps/gladevcp для запуска примеров и начальных версий ваших собственных проектов.

9. FAQ

  1. Я получаю неожиданное событие unmap в моей функции-обработчике сразу после запуска. Что это?

    Это является следствием того, что в вашем файле пользовательского интерфейса Glade для свойства window1 Visible установлено значение True, а также переназначение родительского окна GladeVCP на AXIS или Touchy. Создается дерево виджетов GladeVCP, включая окно верхнего уровня, а затем переродится в AXIS, в результате чего это окно верхнего уровня остается бесхозным. Чтобы избежать зависания этого бесполезного пустого окна, оно не отображается (сделано невидимым), что и является причиной получаемого вами сигнала отмены отображения. Предлагаемое исправление: установите для window1.visible значение False и игнорируйте начальное событие unmap.

  2. Моя программа GladeVCP запускается, но не появляется ожидаемое окно?

    Окно, которое AXIS выделяет для GladeVCP, получит естественный размер всех своих дочерних виджетов вместе взятых. Задача дочернего виджета — запросить размер (ширину и/или высоту). Однако не все виджеты запрашивают ширину больше 0, например виджет Graph в его текущей форме. Если в вашем файле Glade есть такой виджет, и именно он определяет макет, возможно, вы захотите явно установить его ширину. Обратите внимание, что установка свойств ширины и высоты window1 в Glade не имеет смысла, поскольку это окно станет осиротевшим во время повторного родительского контроля, и, следовательно, его геометрия не будет влиять на макет (см. выше). Общее правило таково: если вы вручную запускаете файл пользовательского интерфейса с помощью gladevcp <uifile> и его окно имеет разумную геометрию, оно также должно корректно отображаться в AXIS.

  3. Хочу мигающий светодиод, но он не мигает

    Я установил галочку, чтобы он мигал с интервалом 100 мс. Он не мигает, и я получаю предупреждение при запуске: Внимание: значение "0" типа gint недопустимо или выходит за пределы диапазона свойства led-blink-rate типа gint? Похоже, это ошибка Glade. Просто введите в поле частоту моргания и снова сохраните — у меня это работает.

  4. Моя панель GladeVCP в AXIS не сохраняет состояние, когда я закрываю AXIS, хотя я определил обработчик on_destroy, связанный с сигналом уничтожения окна

    Скорее всего, этот обработчик связан с окном window1, которое из-за переоформления невозможно использовать для этой цели. Пожалуйста, свяжите обработчик on_destroy с сигналом уничтожения внутреннего окна. Например, у меня есть блокнот внутри window1, и я связал on_destroy с сигналом уничтожения блокнотов, и это работает нормально. Это не работает для window1.

  5. Я хочу установить цвет фона или текст виджета HAL_Label в зависимости от его значения контакта HAL

    См. пример в configs/apps/gladevcp/colored-label. Установить цвет фона виджета GtkLabel (а HAL_Label является производным от GtkLabel) немного сложно. Виджет GtkLabel не имеет собственного объекта окна по соображениям производительности, и только объекты окна могут иметь цвет фона. Решение состоит в том, чтобы поместить метку в контейнер EventBox, который имеет окно, но в противном случае невидим — см. файл colorlabel.ui.

Я определил виджет hal_spinbutton в Glade и установил свойство value по умолчанию в соответствующей настройке. Получается ноль?

Это связано с ошибкой в старой версии Gtk, поставляемой с Ubuntu 8.04 и 10.04, и, скорее всего, это относится ко всем виджетам, использующим настройку. Обходной путь, упомянутый, например, в http://osdir.com/ml/gtk-app-devel-list/2010-04/msg00129.html, не позволяет надежно установить значение контакта HAL, лучше установить его явно в ` on_realize` обработчик сигнала во время создания виджета. См. пример в configs/apps/gladevcp/by-widget/spinbutton.{ui,py}.

10. Решение проблем

  • Убедитесь, что у вас установлена версия LinuxCNC для разработки. Вам больше не нужен файл axisrc, об этом упоминалось на старой вики-странице GladeVCP.

  • Запустите GladeVCP или AXIS из окна терминала. Если вы получаете ошибки Python, проверьте, существует ли еще файл /usr/lib/python2.6/dist-packages/hal.so, помимо более нового /usr/lib/python2.6/dist-packages/_hal. .so (обратите внимание на подчеркивание); если да, удалите файл hal.so. Он был заменен файлом hal.py в том же каталоге и сбивает с толку механизм импорта.

  • Если вы используете запуск на месте, выполните команду make clean, чтобы удалить случайно оставшийся файл hal.so, а затем выполните команду make.

  • Если вы используете виджеты HAL_table или HAL_HBox, имейте в виду, что с ними связан контакт HAL, который по умолчанию отключен. Этот контакт контролирует, активны или нет дочерние элементы этого контейнера.

11. Примечание по реализации: обработка ключей в AXIS

Мы считаем, что обработка ключей работает нормально, но, поскольку это новый код, мы рассказываем вам о нем, чтобы вы могли следить за проблемами; пожалуйста, сообщите нам об ошибках или странном поведении. Это история:

AXIS использует набор виджетов TkInter. Приложения GladeVCP используют виджеты Gtk и запускаются в контексте отдельного процесса. Они подключены к AXIS с помощью протокола Xembed. Это позволяет дочернему приложению, такому как GladeVCP, правильно разместиться в родительском окне и, теоретически, иметь встроенную обработку событий.

Однако это предполагает, что и родительское, и дочернее приложение должным образом поддерживают протокол Xembed, что Gtk поддерживает, а TkInter — нет. Следствием этого является то, что некоторые ключи не будут правильно пересылаться с панели GladeVCP в AXIS ни при каких обстоятельствах. Одной из таких ситуаций был случай, когда виджет Entry или SpinButton имел фокус: в этом случае, например, клавиша Escape не была бы перенаправлена в AXIS и не вызвала бы аварийное завершение работы, как должно, с потенциально катастрофическими последствиями.

Таким образом, ключевые события в GladeVCP обрабатываются явно и выборочно пересылаются в AXIS, чтобы гарантировать, что такие ситуации не могут возникнуть. Подробности см. в функции keyboard_forward() в lib/python/gladevcp/xembed.py.

12. Добавление пользовательских виджетов

В Wiki LinuxCNC есть информация о добавлении пользовательских виджетов в GladeVCP. Пользовательские виджеты GladeVCP

13. Вспомогательные приложения GladeVCP

Поддержка предоставляется для независимо установленных приложений GladeVCP, которые соответствуют размещению в системном каталоге, как определено элементами LINUXCNC_AUX_GLADEVCP и LINUXCNC_AUX_EXAMPLES, сообщаемыми скриптом linuxcnc_var:

$ linuxcnc_var LINUXCNC_AUX_GLADEVCP
/usr/share/linuxcnc/aux_gladevcp
$ linuxcnc_var LINUXCNC_AUX_EXAMPLES
/usr/share/linuxcnc/aux_examples

Системный каталог, определенный LINUXCNC_AUX_GLADEVCP (/usr/share/linuxcnc/aux_gladevcp), указывает расположение файлов Python, совместимых с GladeVCP, и связанных с ним подкаталогов. Файл Python импортируется при запуске GladeVCP и становится доступным для последующих приложений GladeVCP, включая встроенное использование в поддержке ГИП'ов.

Системный каталог, определенный LINUXCNC_AUX_EXAMPLES (/usr/share/linuxcnc/aux_examples), определяет расположение примерных подкаталогов конфигурации, используемых для вспомогательных приложений. См. раздел Начало работы/Запуск LinuxCNC на предмет Adding Configuration Selection Items.

Для тестирования можно указать спецификацию времени выполнения вспомогательных приложений с помощью экспортированной переменной среды: GLADEVCP_EXTRAS. Эта переменная должна представлять собой список путей из одного или нескольких каталогов конфигурации, разделенных знаком (:). Обычно эта переменная задается в оболочке, запускающей linuxcnc, или в сценарии запуска ~/.profile пользователя. Пример:

export GLADEVCP_EXTRAS=~/mygladevcp:/opt/othergladevcp

Файлы, найденные в каталогах, указанных с помощью переменной среды GLADEVCP_EXTRAS, заменяют файлы с одинаковыми именами в подкаталогах системного каталога, указанных LINUXNC_AUX_GLADEVCP (например, /usr/share/linuxcnc/aux_gladevcp). Это положение позволяет разработчику тестировать приложение, экспортируя GLADEVCP_EXTRAS, чтобы указать частный каталог приложения, не удаляя каталог приложения, установленный в системе. Сообщения, указывающие на отклоненные дубликаты, выводятся на стандартный вывод.

Note

Для поддержки вспомогательных приложений GladeVCP требуется модуль Python с именем importlib. Этот модуль может быть недоступен в старых версиях, таких как Ubuntu-Lucid.