section_action_events.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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:
  55. The function needs to transfer the whole state of the passed function to the process, which is done with pickle.
  56. It is encouraged to create free functions or static methods which get all the data as simple parameters (i.e. no class or UI logic)
  57. and return the result, instead of writing it in class properties or global variables.
  58. ''')
  59. def cpu_bound_demo():
  60. import time
  61. from nicegui import run
  62. def compute_sum(a: float, b: float) -> float:
  63. time.sleep(1) # simulate a long-running computation
  64. return a + b
  65. async def handle_click():
  66. result = await run.cpu_bound(compute_sum, 1, 2)
  67. ui.notify(f'Sum is {result}')
  68. # ui.button('Compute', on_click=handle_click)
  69. # END OF DEMO
  70. async def mock_click():
  71. import asyncio
  72. await asyncio.sleep(1)
  73. ui.notify('Sum is 3')
  74. ui.button('Compute', on_click=mock_click)
  75. @doc.demo('Running I/O-bound tasks', '''
  76. NiceGUI provides an `io_bound` function for running I/O-bound tasks in a separate thread.
  77. This is useful for long-running I/O operations that would otherwise block the event loop and make the UI unresponsive.
  78. The function returns a future that can be awaited.
  79. ''')
  80. def io_bound_demo():
  81. import requests
  82. from nicegui import run
  83. async def handle_click():
  84. URL = 'https://httpbin.org/delay/1'
  85. response = await run.io_bound(requests.get, URL, timeout=3)
  86. ui.notify(f'Downloaded {len(response.content)} bytes')
  87. ui.button('Download', on_click=handle_click)
  88. doc.intro(run_javascript_documentation)
  89. doc.intro(clipboard_documentation)
  90. @doc.demo('Events', '''
  91. You can register coroutines or functions to be called for the following events:
  92. - `app.on_startup`: called when NiceGUI is started or restarted
  93. - `app.on_shutdown`: called when NiceGUI is shut down or restarted
  94. - `app.on_connect`: called for each client which connects (optional argument: nicegui.Client)
  95. - `app.on_disconnect`: called for each client which disconnects (optional argument: nicegui.Client)
  96. - `app.on_exception`: called when an exception occurs (optional argument: exception)
  97. When NiceGUI is shut down or restarted, all tasks still in execution will be automatically canceled.
  98. ''')
  99. def lifecycle_demo():
  100. from datetime import datetime
  101. from nicegui import app
  102. # dt = datetime.now()
  103. def handle_connection():
  104. global dt
  105. dt = datetime.now()
  106. app.on_connect(handle_connection)
  107. label = ui.label()
  108. ui.timer(1, lambda: label.set_text(f'Last new connection: {dt:%H:%M:%S}'))
  109. # END OF DEMO
  110. global dt
  111. dt = datetime.now()
  112. @doc.demo(app.shutdown)
  113. def shutdown_demo():
  114. from nicegui import app
  115. # ui.button('shutdown', on_click=app.shutdown)
  116. #
  117. # ui.run(reload=False)
  118. # END OF DEMO
  119. ui.button('shutdown', on_click=lambda: ui.notify(
  120. 'Nah. We do not actually shutdown the documentation server. Try it in your own app!'))
  121. doc.intro(storage_documentation)