output_usage.py 10 KB

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