action_events.py 5.1 KB

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