section_action_events.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. from nicegui import app, ui
  2. from . import (
  3. clipboard_documentation,
  4. doc,
  5. generic_events_documentation,
  6. keyboard_documentation,
  7. refreshable_documentation,
  8. run_javascript_documentation,
  9. storage_documentation,
  10. timer_documentation,
  11. )
  12. doc.title('Action & *Events*')
  13. doc.intro(timer_documentation)
  14. doc.intro(keyboard_documentation)
  15. @doc.demo('UI Updates', '''
  16. NiceGUI tries to automatically synchronize the state of UI elements with the client,
  17. e.g. when a label text, an input value or style/classes/props of an element have changed.
  18. In other cases, you can explicitly call `element.update()` or `ui.update(*elements)` to update.
  19. The demo code shows both methods for a `ui.echart`, where it is difficult to automatically detect changes in the `options` dictionary.
  20. ''')
  21. def ui_updates_demo():
  22. from random import random
  23. chart = ui.echart({
  24. 'xAxis': {'type': 'value'},
  25. 'yAxis': {'type': 'value'},
  26. 'series': [{'type': 'line', 'data': [[0, 0], [1, 1]]}],
  27. })
  28. def add():
  29. chart.options['series'][0]['data'].append([random(), random()])
  30. chart.update()
  31. def clear():
  32. chart.options['series'][0]['data'].clear()
  33. ui.update(chart)
  34. with ui.row():
  35. ui.button('Add', on_click=add)
  36. ui.button('Clear', on_click=clear)
  37. doc.intro(refreshable_documentation)
  38. @doc.demo('Async event handlers', '''
  39. Most elements also support asynchronous event handlers.
  40. Note: You can also pass a `functools.partial` into the `on_click` property to wrap async functions with parameters.
  41. ''')
  42. def async_handlers_demo():
  43. import asyncio
  44. async def async_task():
  45. ui.notify('Asynchronous task started')
  46. await asyncio.sleep(5)
  47. ui.notify('Asynchronous task finished')
  48. ui.button('start async task', on_click=async_task)
  49. doc.intro(generic_events_documentation)
  50. @doc.demo('Running CPU-bound tasks', '''
  51. NiceGUI provides a `cpu_bound` function for running CPU-bound tasks in a separate process.
  52. This is useful for long-running computations that would otherwise block the event loop and make the UI unresponsive.
  53. The function returns a future that can be awaited.
  54. NOTE: The function needs to transfer the whole state of the passed function to the process (which is done with pickle).
  55. It is encouraged to create static methods (or free functions) which get all the data as simple parameters (eg. no class/ui logic)
  56. and return the result (instead of writing it in class properties or global variables).
  57. ''')
  58. def cpu_bound_demo():
  59. import time
  60. from nicegui import run
  61. def compute_sum(a: float, b: float) -> float:
  62. time.sleep(1) # simulate a long-running computation
  63. return a + b
  64. async def handle_click():
  65. result = await run.cpu_bound(compute_sum, 1, 2)
  66. ui.notify(f'Sum is {result}')
  67. # ui.button('Compute', on_click=handle_click)
  68. # END OF DEMO
  69. async def mock_click():
  70. import asyncio
  71. await asyncio.sleep(1)
  72. ui.notify('Sum is 3')
  73. ui.button('Compute', on_click=mock_click)
  74. @doc.demo('Running I/O-bound tasks', '''
  75. NiceGUI provides an `io_bound` function for running I/O-bound tasks in a separate thread.
  76. This is useful for long-running I/O operations that would otherwise block the event loop and make the UI unresponsive.
  77. The function returns a future that can be awaited.
  78. ''')
  79. def io_bound_demo():
  80. import requests
  81. from nicegui import run
  82. async def handle_click():
  83. URL = 'https://httpbin.org/delay/1'
  84. response = await run.io_bound(requests.get, URL, timeout=3)
  85. ui.notify(f'Downloaded {len(response.content)} bytes')
  86. ui.button('Download', on_click=handle_click)
  87. doc.intro(run_javascript_documentation)
  88. doc.intro(clipboard_documentation)
  89. @doc.demo('Events', '''
  90. You can register coroutines or functions to be called for the following events:
  91. - `app.on_startup`: called when NiceGUI is started or restarted
  92. - `app.on_shutdown`: called when NiceGUI is shut down or restarted
  93. - `app.on_connect`: called for each client which connects (optional argument: nicegui.Client)
  94. - `app.on_disconnect`: called for each client which disconnects (optional argument: nicegui.Client)
  95. - `app.on_exception`: called when an exception occurs (optional argument: exception)
  96. When NiceGUI is shut down or restarted, all tasks still in execution will be automatically canceled.
  97. ''')
  98. def lifecycle_demo():
  99. from datetime import datetime
  100. from nicegui import app
  101. # dt = datetime.now()
  102. def handle_connection():
  103. global dt
  104. dt = datetime.now()
  105. app.on_connect(handle_connection)
  106. label = ui.label()
  107. ui.timer(1, lambda: label.set_text(f'Last new connection: {dt:%H:%M:%S}'))
  108. # END OF DEMO
  109. global dt
  110. dt = datetime.now()
  111. @doc.demo(app.shutdown)
  112. def shutdown_demo():
  113. from nicegui import app
  114. # ui.button('shutdown', on_click=app.shutdown)
  115. #
  116. # ui.run(reload=False)
  117. # END OF DEMO
  118. ui.button('shutdown', on_click=lambda: ui.notify(
  119. 'Nah. We do not actually shutdown the documentation server. Try it in your own app!'))
  120. doc.intro(storage_documentation)