{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 通用事件\n", "\n", "大多数 UI 元素都带有预定义的事件。例如,演示中的 \"A\" 这样的 `ui.button` 有一个 `on_click` 参数,它期望一个协程或函数。但是,您也可以使用 on 方法来注册一个通用事件处理器,就像 \"B\" 那样。这允许您为 JavaScript 和 Quasar 支持的任何事件注册处理器。\n", "\n", "例如,即使 `ui.button` 没有 `on_mousemove` 参数,您也可以像 \"C\" 那样为 `mousemove` 事件注册处理器。有些事件,比如 mousemove,会非常频繁地触发。为了避免性能问题,您可以使用 throttle 参数,以便每 throttle 秒只调用一次处理器(\"D\")。\n", "\n", "通用事件处理器可以是同步的或异步的,并且可以选择性地接受 `GenericEventArguments` 作为参数(\"E\")。您还可以指定应该将 JavaScript 或 Quasar 事件的哪些属性传递给处理器(\"F\")。这可以减少需要在服务器和客户端之间传输的数据量。\n", "\n", "在这里,您可以找到有关支持的事件的更多信息:\n", "\n", "- 适用于 HTML 元素\n", "- 适用于基于 Quasar 的元素(在单个组件页面上查看“Events”标签)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from nicegui import ui\n", "\n", "with ui.row():\n", " ui.button('A', on_click=lambda: ui.notify('You clicked the button A.'))\n", " ui.button('B').on('click', lambda: ui.notify('You clicked the button B.'))\n", "with ui.row():\n", " ui.button('C').on('mousemove', lambda: ui.notify('You moved on button C.'))\n", " ui.button('D').on('mousemove', lambda: ui.notify('You moved on button D.'), throttle=0.5)\n", "with ui.row():\n", " ui.button('E').on('mousedown', lambda e: ui.notify(e))\n", " ui.button('F').on('mousedown', lambda e: ui.notify(e), ['ctrlKey', 'shiftKey'])\n", "\n", "# ui.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 指定事件属性\n", "\n", "一个字符串列表命名了 JavaScript 事件对象的属性:\n", "\n", "```python\n", "ui.button().on('click', handle_click, ['clientX', 'clientY'])\n", "```\n", "\n", "一个空列表请求没有属性:\n", "\n", "```python\n", "ui.button().on('click', handle_click, [])\n", "```\n", "\n", "值 `None` 表示所有属性(默认):\n", "\n", "```python\n", "ui.button().on('click', handle_click, None)\n", "```\n", "\n", "如果事件像 QTable 的 `\"row-click\"`(evt, row, index)=> void 那样调用多个参数,您可以定义一个参数定义列表:\n", "\n", "```python\n", "ui.table(...).on('rowClick', handle_click, [[], ['name'], None])\n", "```\n", "\n", "在此示例中,`\"row-click\"` 事件将省略第一个 `evt` 参数的所有参数,仅发送 row 参数的 `\"name\"` 属性,并发送完整的 `index`。\n", "\n", "如果检索到的事件参数列表长度为 1,则参数会自动解包。因此,您可以写:\n", "\n", "```python\n", "ui.button().on('click', lambda e: print(e.args['clientX'], flush=True))\n", "```\n", "\n", "而不是:\n", "\n", "```python\n", "ui.button().on('click', lambda e: print(e.args[0]['clientX'], flush=True))\n", "```\n", "\n", "请注意,默认情况下,会发送所有参数的所有可 JSON 序列化的属性。这样做是为了简化注册新事件和发现它们的属性。如果带宽有问题,应该将参数限制在服务器实际需要的内容上。" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from nicegui import ui\n", "\n", "columns = [\n", " {'name': 'name', 'label': 'Name', 'field': 'name'},\n", " {'name': 'age', 'label': 'Age', 'field': 'age'},\n", "]\n", "rows = [\n", " {'name': 'Alice', 'age': 42},\n", " {'name': 'Bob', 'age': 23},\n", "]\n", "ui.table(columns, rows, 'name').on('rowClick', ui.notify, [[], ['name'], None])\n", "\n", "# ui.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 修饰符\n", "\n", "您还可以包含[键修饰符](https://vuejs.org/guide/essentials/event-handling.html#key-modifiers%3E)(输入 \"A\" 中所示)、修饰符组合(输入 \"B\" 中所示)和[事件修饰符](https://vuejs.org/guide/essentials/event-handling.html#mouse-button-modifiers%3E)(输入 \"C\" 中所示)。" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from nicegui import ui\n", "\n", "with ui.row():\n", " ui.input('A').classes('w-12').on('keydown.space', lambda: ui.notify('You pressed space.'))\n", " ui.input('B').classes('w-12').on('keydown.y.shift', lambda: ui.notify('You pressed Shift+Y'))\n", " ui.input('C').classes('w-12').on('keydown.once', lambda: ui.notify('You started typing.'))\n", "\n", "# ui.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 自定义事件\n", "\n", "使用 `emitEvent(...)` 从 JavaScript 发出自定义事件非常简单,可以使用 `ui.on(...)` 进行监听。如果您希望在 JavaScript 中发生某事时调用 Python 代码,这可能会很有用。在这个例子中,我们正在监听浏览器标签页的 `visibilitychange` 事件。" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from nicegui import ui\n", "\n", "tabwatch = ui.checkbox('Watch browser tab re-entering')\n", "ui.on('tabvisible', lambda: ui.notify('Welcome back!') if tabwatch.value else None)\n", "ui.add_head_html('''\n", " \n", "''')\n", "\n", "# ui.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 纯 JavaScript 事件\n", "\n", "您还可以使用 on 方法注册纯 JavaScript 事件处理器。如果您想在不向服务器发送任何数据的情况下调用 JavaScript 代码,这可能会很有用。在这个例子中,我们正在使用 `navigator.clipboard` API 将字符串复制到剪贴板。" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from nicegui import ui\n", "\n", "ui.button('Copy to clipboard') \\\n", " .on('click', js_handler='''() => {\n", " navigator.clipboard.writeText(\"Hello, NiceGUI!\");\n", " }''')\n", "\n", "# ui.run()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "py311", "language": "python", "name": "python3" }, "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.11.7" } }, "nbformat": 4, "nbformat_minor": 2 }