2025, Dec 11 21:01
Как правильно передать user_data в колбэк Dear PyGui
Почему в колбэк Dear PyGui приходит тег sender вместо user_data, и как это исправить. Пояснение сигнатуры (sender, app_data, user_data) и минимальный пример.
Передача данных в UI‑колбэки кажется простым делом, пока ожидаемое значение не оказывается другим. В Dear PyGui частая ловушка — при использовании user_data в вывод попадает тег кнопки вместо вашего полезного объекта. Причина не в том, как вы прикрепляете данные, а в сигнатуре функции‑обработчика.
Минимальный пример, воспроизводящий проблему
В этом фрагменте к каждой кнопке привязывается колбэк и передаётся целочисленный индекс через user_data. В итоге на печать выходит тег кнопки, а не сам индекс.
import dearpygui.dearpygui as dpg
for idx in range(N):
with dpg.group(horizontal=True):
dpg.add_button(label="add", tag="btn_add_" + str(idx))
dpg.set_item_callback(item="btn_add_" + str(idx), callback=on_add_click)
dpg.set_item_user_data(item="btn_add_" + str(idx), user_data=idx)
def on_add_click(payload):
print(f"on_add_click: {payload}")
Что на самом деле происходит
Dear PyGui передаёт в колбэк три позиционных аргумента: sender, app_data и user_data. Если функция объявлена с одним параметром, он получает первый аргумент — sender. Для кнопки sender — это её тег. Поэтому в выводе вы видите что-то вроде btn_add_0 вместо целого числа, которое пытались передать.
Такое поведение библиотеки описано в официальном руководстве по колбэкам элементов: https://dearpygui.readthedocs.io/en/latest/documentation/item-callbacks.html.
Как исправить
Объявите обработчик с тремя параметрами, чтобы третий получил переданный вами user_data. Если sender и app_data не нужны, их можно игнорировать.
def on_add_click(sender, app_data, payload):
print(f"on_add_click: {payload}")
Можно сразу задать callback и user_data при создании элемента, обойдясь без отдельных вызовов сеттеров.
import dearpygui.dearpygui as dpg
def on_add_click(sender, app_data, payload):
print(f"on_add_click: {payload}")
for idx in range(N):
with dpg.group(horizontal=True):
dpg.add_button(
label="add",
tag="btn_add_" + str(idx),
callback=on_add_click,
user_data=idx,
)
Почему это важно
Знание точной сигнатуры колбэка экономит время и избавляет от скрытых ошибок, когда по логике незаметно проходит не то значение. Это снижает путаницу при отладке поведения интерфейса и делает обработку событий предсказуемой. Как только сигнатура функции соответствует соглашению вызова Dear PyGui, user_data ведёт себя стабильно — будь то целочисленный индекс или любая другая полезная нагрузка.
Выводы
Если в колбэке Dear PyGui вы собираетесь использовать user_data, объявляйте функцию с тремя позиционными параметрами: sender, app_data и user_data. Печатайте или обрабатывайте только третий, если вам нужен лишь он. Для аккуратности кода callback и user_data удобно передавать прямо в add_button — это равноценно установке через отдельные вызовы.