output_usage.py 9.9 KB

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