运行截图
思路
设置侧边栏的 z > 0, 这样可以在靠上的图层显示.
如何隐藏和显示侧边栏, 通过修改 Widget.visible
属性即可.
怎么添加展开/折叠过程的动画, 参考官方的动画示例, 我们可以用 Widget.animate(<属性名>, <值>)
实现.
源代码 (带注释)
from textual.app import App
from textual.reactive import Reactive
from textual.widgets import Placeholder
class Sidebar(Placeholder):
show_bar = Reactive(False)
def __init__(self):
super().__init__()
self.layout_offset_x = -40 # noqa
# 由外界控制 show_bar 的翻转. 当 show_bar 的值发生变化时, 自动触发这个方法.
async def watch_show_bar(self, value: bool):
self.animate('layout_offset_x', 0 if value else -40)
class MainApp(App):
sidebar: Sidebar
async def on_load(self):
# 这是父类的内置方法. 在 loading 生命阶段, 我们去做一些热键绑定.
# 这里我绑定了键盘 `b` 为切换侧边栏的快捷键.
await self.bind('b', 'toggle_side_bar', 'Toggle Sidebar')
# 这也是由 textual 的魔术机制实现的自动生成的方法名称. 我们在这里完成按下热
# 键时的逻辑.
async def action_toggle_side_bar(self):
# 注意 self.sidebar.show_bar 的返回值不是 Reactive, 而是 bool 类型.
# 个人猜测 textual 在内部修改了 Reactive 的 __getattr__ 和 __setattr__
# 的默认行为实现的.
self.sidebar.show_bar = not self.sidebar.show_bar
async def on_mount(self):
# 为了让效果看着更明显, 我们加一些无关的组件.
await self.view.dock(
Placeholder(), Placeholder(), Placeholder(),
edge='top'
)
# 注意把侧边栏放在最上面 (z 值调高).
self.sidebar = Sidebar()
await self.view.dock(self.sidebar, edge='left', size=40, z=1)
MainApp.run()
运行:
# 假设将上述源代码保存到了 "demo.py".
python3 demo.py
参考
- 官方动画示例 (搜索 "def watch_show_bar"): github.com/Textualize/…
- kaskade help 组件的用例 (搜索 "self.help_widget"): github.com/sauljabin/k…