JupyterLab如何实现点击标题折叠展开对应部分输出内容
问题场景
在JupyterLab代码块中运行for循环逻辑时,每轮循环都会输出列表对应索引的汇总DataFrame与绘制图表;实际使用场景下有20余个循环标题,每个标题下对应多个DataFrame与图表,导致输出区域内容过长,存在阅读困难、导航不便的问题。
示例初始代码
import numpy as np import pandas as pd import matplotlib.pyplot as plt from IPython.display import HTML for i in range(2): display(HTML(f'<h3> [-] Running code for {i} </h3>')) # 计算逻辑 d = pd.DataFrame({'X': np.random.rand(10), 'Y': np.random.rand(10)}) corr = d.corr() # 输出结果表格与图表 display(corr) d.plot(figsize=(5, 3)) plt.show()
需求
实现交互式折叠效果:将每轮循环对应的标题作为切换开关,点击标题即可折叠该标题下属的所有输出内容,再次点击则重新展开,优化长输出的浏览体验。
实现方案
无需安装第三方Jupyter插件,基于原生HTML+少量JS即可实现交互折叠能力,核心逻辑是为每轮循环的输出内容包裹独立容器,给标题绑定点击事件,触发时切换容器的显隐状态、同步更新折叠标识。
可直接运行的完整代码如下:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from IPython.display import HTML, display import uuid # 仅需注入一次全局样式,重复运行不会产生冗余 display(HTML(""" <style> .collapse-title { cursor: pointer; user-select: none; padding: 6px 0; margin: 8px 0; } .collapse-content { padding-left: 12px; border-left: 3px solid #e0e0e0; margin-bottom: 16px; } </style> """)) for i in range(2): # 生成短随机唯一ID,避免多轮/多次运行元素冲突 block_id = f"collapse_{uuid.uuid4().hex[:8]}" # 输出绑定点击事件的折叠标题 display(HTML(f''' <h3 class="collapse-title" onclick=" const contentDom = document.getElementById('{block_id}'); const marker = this.querySelector('.collapse-marker'); if (contentDom.style.display === 'none') {{ contentDom.style.display = 'block'; marker.textContent = '[-]'; }} else {{ contentDom.style.display = 'none'; marker.textContent = '[+]'; }} "><span class="collapse-marker">[-]</span> Running code for {i}</h3> <div class="collapse-content" id="{block_id}"> ''')) # 原有业务计算与输出逻辑无需修改 d = pd.DataFrame({'X': np.random.rand(10), 'Y': np.random.rand(10)}) corr = d.corr() display(corr) d.plot(figsize=(5, 3)) plt.show() # 闭合当前轮次的内容容器 display(HTML('</div>'))
效果说明
- 默认所有轮次内容为展开状态,标题前缀显示
[-] - 点击对应轮次标题即可收起该轮次下全部DataFrame、图表输出,标题前缀切换为
[+] - 再次点击标题即可重新展开对应内容
- 每轮容器使用随机唯一ID,多次运行、多轮循环都不会出现元素冲突
- 内置简单的左侧分割线样式区分折叠层级,不需要可直接删除对应CSS代码
如果需要默认初始状态为全部折叠,只需将内容容器的初始样式加style="display: none;",同时把标题初始前缀改为[+]即可。
内容的提问来源于stack exchange,提问作者user5828964
相关产品推荐
相关产品推荐

