output_usage.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. """
  2. 输出演示
  3. ^^^^^^^^^^^
  4. 演示PyWebIO支持的各种输出形式
  5. :demo_host:`Demo地址 </?pywebio_api=output_usage>` `源码 <https://github.com/wang0618/PyWebIO/blob/dev/demos/output_usage.py>`_
  6. """
  7. from pywebio import start_server
  8. from pywebio.output import *
  9. from pywebio.session import hold, set_env
  10. from functools import partial
  11. def code_block(code, strip_indent=4):
  12. if strip_indent:
  13. lines = (
  14. i[strip_indent:] if (i[:strip_indent] == ' ' * strip_indent) else i
  15. for i in code.splitlines()
  16. )
  17. code = '\n'.join(lines)
  18. code = code.strip('\n')
  19. def run_code(code, scope):
  20. with use_scope(scope):
  21. exec(code, globals())
  22. with use_scope() as scope:
  23. put_code(code, 'python')
  24. put_buttons([{'label': '运行', 'value': '', 'color': 'success'}],
  25. onclick=[partial(run_code, code=code, scope=scope)], small=True)
  26. async def main():
  27. """PyWebIO输出演示
  28. 演示PyWebIO支持的各种输出形式
  29. """
  30. put_markdown("""# PyWebIO 输出演示
  31. 在[这里](https://github.com/wang0618/PyWebIO/blob/dev/demos/output_usage.py)可以获取本Demo的源码。
  32. 本Demo仅提供了PyWebIO输出模块的部分功能的演示,完整特性请参阅[用户指南](https://pywebio.readthedocs.io/zh_CN/latest/guide.html)。
  33. PyWebIO的输出函数都定义在 `pywebio.output` 模块中,可以使用 `from pywebio.output import *` 引入。
  34. ### 基本输出
  35. PyWebIO提供了一些便捷函数来输出表格、链接等格式:
  36. """, strip_indent=4)
  37. code_block(r"""
  38. # 文本输出
  39. put_text("Hello world!")
  40. # 表格输出
  41. put_table([
  42. ['商品', '价格'],
  43. ['苹果', '5.5'],
  44. ['香蕉', '7'],
  45. ])
  46. # Markdown输出
  47. put_markdown('~~删除线~~')
  48. # 文件输出
  49. put_file('hello_word.txt', b'hello word!')
  50. """)
  51. put_markdown(r"""PyWebIO提供的全部输出函数请参考PyWebIO文档
  52. ### 组合输出
  53. 函数名以 `put_` 开始的输出函数,可以与一些输出函数组合使用,作为最终输出的一部分。
  54. 比如`put_table()`支持以`put_xxx()`调用作为单元格内容:
  55. """, strip_indent=4)
  56. code_block(r"""
  57. put_table([
  58. ['Type', 'Content'],
  59. ['html', put_html('X<sup>2</sup>')],
  60. ['text', '<hr/>'], # 等价于 ['text', put_text('<hr/>')]
  61. ['buttons', put_buttons(['A', 'B'], onclick=toast)],
  62. ['markdown', put_markdown('`Awesome PyWebIO!`')],
  63. ['file', put_file('hello.text', b'hello world')],
  64. ['table', put_table([['A', 'B'], ['C', 'D']])]
  65. ])
  66. """)
  67. put_markdown(r"""类似地,`popup()`也可以将`put_xxx()`调用作为弹窗内容:
  68. """, strip_indent=4)
  69. code_block(r"""
  70. popup('Popup title', [
  71. put_html('<h3>Popup Content</h3>'),
  72. 'plain html: <br/>', # 等价于 put_text('plain html: <br/>')
  73. put_table([['A', 'B'], ['C', 'D']]),
  74. put_buttons(['close_popup()'], onclick=lambda _: close_popup())
  75. ])
  76. """)
  77. put_markdown(r"更多接受`put_xxx()`作为参数的输出函数请参考函数文档。")
  78. put_markdown(r"""### 事件回调
  79. PyWebIO允许你输出一些控件,当控件被点击时执行提供的回调函数,就像编写GUI程序一样。
  80. 下面是一个例子:
  81. ```python
  82. from functools import partial
  83. def edit_row(choice, row):
  84. put_markdown("> You click`%s` button ar row `%s`" % (choice, row))
  85. put_table([
  86. ['Idx', 'Actions'],
  87. [1, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=1))],
  88. [2, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=2))],
  89. [3, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=3))],
  90. ])
  91. ```
  92. `put_table()`的调用不会阻塞。当用户点击了某行中的按钮时,PyWebIO会自动调用相应的回调函数:
  93. """, strip_indent=4)
  94. from functools import partial
  95. @use_scope('table-callback')
  96. def edit_row(choice, row):
  97. put_markdown("> You click `%s` button ar row `%s`" % (choice, row))
  98. put_table([
  99. ['Idx', 'Actions'],
  100. [1, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=1))],
  101. [2, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=2))],
  102. [3, put_buttons(['edit', 'delete'], onclick=partial(edit_row, row=3))],
  103. ])
  104. set_scope('table-callback')
  105. put_markdown(r"""当然,PyWebIO还支持单独的按钮控件:
  106. ```python
  107. def btn_click(btn_val):
  108. put_markdown("> You click `%s` button" % btn_val)
  109. put_buttons(['A', 'B', 'C'], onclick=btn_click)
  110. ```
  111. """, strip_indent=4)
  112. @use_scope('button-callback')
  113. def btn_click(btn_val):
  114. put_markdown("> You click `%s` button" % btn_val)
  115. put_buttons(['A', 'B', 'C'], onclick=btn_click)
  116. set_scope('button-callback')
  117. put_markdown(r"""### 输出域Scope
  118. PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWebIO的内容输出区可以划分出不同的输出域,PyWebIO将输出域称作`Scope`。
  119. 输出域为输出内容的容器,各个输出域之间上下排列,输出域也可以进行嵌套。
  120. 每个输出函数(函数名形如 `put_xxx()` )都会将内容输出到一个Scope,默认为”当前Scope”,”当前Scope”由运行时上下文确定,输出函数也可以手动指定输出到的Scope。Scope名在会话内唯一。
  121. 可以使用 `use_scope()` 开启并进入一个新的输出域,或进入一个已经存在的输出域:
  122. ```python
  123. with use_scope('A'):
  124. put_text('Text in scope A')
  125. with use_scope('B'):
  126. put_text('Text in scope B')
  127. with use_scope('C'):
  128. put_text('Text in scope C')
  129. ```
  130. 以上代码将会产生如下Scope布局:
  131. """, strip_indent=4)
  132. with use_scope('A'):
  133. put_text('Text in scope A')
  134. with use_scope('B'):
  135. put_text('Text in scope B')
  136. with use_scope('C'):
  137. put_text('Text in scope C')
  138. put_html("""<style>
  139. #pywebio-scope-A {border: 1px solid red;}
  140. #pywebio-scope-B {border: 1px solid blue;margin:2px}
  141. #pywebio-scope-C {border: 1px solid green;margin-top:2px}
  142. </style><br/>""")
  143. put_markdown(r"""
  144. 输出函数(函数名形如 `put_xxx()` )在默认情况下,会将内容输出到”当前Scope”,可以通过 `use_scope()` 设置运行时上下文的”当前Scope”。
  145. 此外,也可以通过输出函数的 scope 参数指定输出的目的Scope:
  146. """, strip_indent=4)
  147. put_grid([
  148. [put_code("put_text('A', scope='A')", 'python'), None, put_buttons(['运行'], [lambda: put_text('A', scope='A')])],
  149. [put_code("put_text('B', scope='B')", 'python'), None, put_buttons(['运行'], [lambda: put_text('B', scope='B')])],
  150. [put_code("put_text('C', scope='C')", 'python'), None, put_buttons(['运行'], [lambda: put_text('C', scope='C')])],
  151. ], cell_widths='1fr 10px auto')
  152. put_markdown(r"""输出函数可以使用position参数指定内容在Scope中输出的位置
  153. ```python
  154. put_text(now(), scope='A', position=...)
  155. ```
  156. """, strip_indent=4)
  157. import datetime
  158. put_buttons([('position=%s' % i, i) for i in [1, 2, 3, -1, -2, -3]],
  159. lambda i: put_text(datetime.datetime.now(), position=i, scope='A'), small=True)
  160. put_markdown(r"除了 `use_scope()` , PyWebIO同样提供了以下scope控制函数: ")
  161. put_grid([
  162. [put_code("clear('B') # 清除Scope B中的内容", 'python'), None, put_buttons(['运行'], [lambda: clear('B')])],
  163. [put_code("remove('C') # 移除Scope C", 'python'), None, put_buttons(['运行'], [lambda: remove('C')])],
  164. [put_code("scroll_to('A') # 将页面滚动到Scope A处", 'python'), None, put_buttons(['运行'], [lambda: scroll_to('A')])],
  165. ], cell_widths='1fr 10px auto')
  166. put_markdown(r"""### 布局
  167. 一般情况下,使用上文介绍的各种输出函数足以完成各种内容的展示,但直接调用输出函数产生的输出之间都是竖直排列的,如果想实现更复杂的布局(比如在页 面左侧显示一个代码块,在右侧显示一个图像),就需要借助布局函数。
  168. `pywebio.output` 模块提供了3个布局函数,通过对他们进行组合可以完成各种复杂的布局:
  169. - `put_row()` : 使用行布局输出内容. 内容在水平方向上排列
  170. - `put_column()` : 使用列布局输出内容. 内容在竖直方向上排列
  171. - `put_grid()` : 使用网格布局输出内容
  172. 比如,通过通过组合 `put_row()` 和 `put_column()` 实现的布局:
  173. """, strip_indent=4)
  174. code_block(r"""
  175. put_row([
  176. put_column([
  177. put_code('A'),
  178. put_row([
  179. put_code('B1'), None, # None 表示输出之间的空白
  180. put_code('B2'), None,
  181. put_code('B3'),
  182. ]),
  183. put_code('C'),
  184. ]), None,
  185. put_code('D'), None,
  186. put_code('E')
  187. ])
  188. """)
  189. put_markdown(r"""
  190. ### 样式
  191. 如果你熟悉 CSS样式 ,你还可以使用 `style()` 函数给输出设定自定义样式。
  192. 可以给单个的 `put_xxx()` 输出设定CSS样式,也可以配合组合输出使用:
  193. """, strip_indent=4)
  194. code_block(r"""
  195. style(put_text('Red'), 'color: red')
  196. put_table([
  197. ['A', 'B'],
  198. ['C', style(put_text('Red'), 'color: red')],
  199. ])
  200. """, strip_indent=4)
  201. put_markdown(r"`style()` 也接受列表作为输入:")
  202. code_block(r"""
  203. style([
  204. put_text('Red'),
  205. put_markdown('~~del~~')
  206. ], 'color: red')
  207. put_collapse('title', style([
  208. put_text('text'),
  209. put_markdown('~~del~~'),
  210. ], 'margin-left: 20px'))
  211. """, strip_indent=4)
  212. put_markdown("""----
  213. PyWebIO的输出演示到这里就结束了,更多内容请访问PyWebIO[用户指南](https://pywebio.readthedocs.io/zh_CN/latest/guide.html)和[output模块文档](https://pywebio.readthedocs.io/zh_CN/latest/output.html)。
  214. """, lstrip=True)
  215. await hold()
  216. if __name__ == '__main__':
  217. start_server(main, debug=True, port=8080, cdn=False)