{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "39647a59",
   "metadata": {},
   "source": [
    "# 17-08 · Объект Event\n",
    "\n",
    "Практика к разделу [«Объект Event»](../../site/chapters/glava-17/17-08-obyekt-event.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19bb05b5",
   "metadata": {},
   "source": [
    "## Цель\n",
    "\n",
    "Посмотреть на реальные поля объекта tkinter.Event для разных типов событий."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3a3179b",
   "metadata": {},
   "source": [
    "## Про mainloop() в этом ноутбуке\n",
    "\n",
    "Вместо `root.mainloop()` здесь используется `root.update()` + `root.destroy()` — приложение строится точно так же, просто без бесконечного ожидания в конце (см. объяснение в ноутбуках главы 16)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8431feee",
   "metadata": {},
   "source": [
    "## Рабочий пример — событие клавиатуры"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "317689c7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:12:37.689186Z",
     "iopub.status.busy": "2026-09-03T10:12:37.689003Z",
     "iopub.status.idle": "2026-09-03T10:12:37.829236Z",
     "shell.execute_reply": "2026-09-03T10:12:37.827448Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'type': '2', 'keysym': 'Return', 'char': '\\r'}\n"
     ]
    }
   ],
   "source": [
    "import tkinter as tk\n",
    "\n",
    "root = tk.Tk()\n",
    "label = tk.Label(root, text=\"...\")\n",
    "label.pack()\n",
    "poslednee = {}\n",
    "\n",
    "def on_key(event):\n",
    "    poslednee[\"type\"] = str(event.type)\n",
    "    poslednee[\"keysym\"] = event.keysym\n",
    "    poslednee[\"char\"] = event.char\n",
    "    label.config(text=f\"keysym={event.keysym!r} char={event.char!r}\")\n",
    "\n",
    "root.bind(\"<Key>\", on_key)\n",
    "root.update()\n",
    "root.focus_force()   # без фокуса окна event_generate для клавиш никуда не доставит событие\n",
    "root.update()\n",
    "label.event_generate(\"<Key>\", keysym=\"Return\")\n",
    "root.update()\n",
    "print(poslednee)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddab790c",
   "metadata": {},
   "source": [
    "## Эксперимент — событие мыши (Enter/Leave)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c8406b97",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:12:37.830765Z",
     "iopub.status.busy": "2026-09-03T10:12:37.830569Z",
     "iopub.status.idle": "2026-09-03T10:12:37.834952Z",
     "shell.execute_reply": "2026-09-03T10:12:37.834384Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'widget': '.!label', 'type': '7'}\n"
     ]
    }
   ],
   "source": [
    "poslednee_mouse = {}\n",
    "\n",
    "def on_enter(event):\n",
    "    poslednee_mouse[\"widget\"] = str(event.widget)\n",
    "    poslednee_mouse[\"type\"] = str(event.type)\n",
    "\n",
    "label.bind(\"<Enter>\", on_enter)\n",
    "root.update()\n",
    "label.event_generate(\"<Enter>\")\n",
    "root.update()\n",
    "print(poslednee_mouse)\n",
    "# Обратите внимание: у события <Enter> event.keysym/event.char не несут полезной информации —\n",
    "# это поля, осмысленные для КЛАВИАТУРНЫХ событий.\n",
    "root.destroy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "748b2578",
   "metadata": {},
   "source": [
    "## Задание ★★ Самостоятельная задача\n",
    "\n",
    "Привяжите `<Button-1>` к отдельному виджету и распечатайте `event.x`/`event.y` — координаты клика внутри виджета."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "907acf92",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:12:37.836154Z",
     "iopub.status.busy": "2026-09-03T10:12:37.835988Z",
     "iopub.status.idle": "2026-09-03T10:12:37.943635Z",
     "shell.execute_reply": "2026-09-03T10:12:37.943038Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Координаты клика внутри виджета: {'x': 12, 'y': 7}\n",
      "event.x/event.y отсчитываются от левого верхнего угла самого виджета, а не экрана.\n"
     ]
    }
   ],
   "source": [
    "root = tk.Tk()\n",
    "metka = tk.Label(root, text=\"Кликните по мне\", width=20, height=3)\n",
    "metka.pack()\n",
    "koordinaty = {}\n",
    "\n",
    "def na_klik(event):\n",
    "    koordinaty[\"x\"] = event.x\n",
    "    koordinaty[\"y\"] = event.y\n",
    "\n",
    "metka.bind(\"<Button-1>\", na_klik)\n",
    "root.update()\n",
    "\n",
    "# программно кликаем в точку (12, 7) ВНУТРИ виджета\n",
    "metka.event_generate(\"<Button-1>\", x=12, y=7)\n",
    "root.update()\n",
    "\n",
    "print(\"Координаты клика внутри виджета:\", koordinaty)\n",
    "assert koordinaty == {\"x\": 12, \"y\": 7}\n",
    "print(\"event.x/event.y отсчитываются от левого верхнего угла самого виджета, а не экрана.\")\n",
    "root.destroy()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
