【问题标题】:Vertical overflow of table in live display should scroll the content实时显示中表格的垂直溢出应该滚动内容
【发布时间】:2021-02-24 16:46:59
【问题描述】:

我正在使用Live 显示来显示随时间增长的Table 的内容。最终会出现垂直溢出,在这种情况下,我希望最旧的(即最上面的)行消失,而最近的行应该与标题一起显示,即内容应该滚动。实时显示的vertical_overflow 参数提供了"visible" 选项,但这会使表格的标题消失。显然这是一个Table 特定的问题,因为标题应该保留但内容应该滚动。

import time
from rich.live import Live
from rich.table import Table

table = Table()
table.add_column('Time')
table.add_column('Message')

with Live(table, refresh_per_second=5, vertical_overflow='visible'):
    for i in range(100):
        time.sleep(0.2)
        table.add_row(time.asctime(), f'Event {i:03d}')

左侧部分显示vertical_overflow='visible' 的行为,右侧部分显示所需的行为:

到目前为止,我正在使用一种解决方法,使用单独的数据结构来保存行,然后在每次添加新行时从头开始创建表。这似乎不是很有效,所以我想知道是否有更好的解决方案。对于多行行,此解决方法也失败,因为它将它们计为单行(因此会发生溢出)。

from collections import deque
import os
import time
from rich.live import Live
from rich.table import Table


def generate_table(rows):
    table = Table()
    table.add_column('Time')
    table.add_column('Message')
    for row in rows:
        table.add_row(*row)
    return table


width, height = os.get_terminal_size()
messages = deque(maxlen=height-4)  # save space for header and footer

with Live(generate_table(messages), refresh_per_second=5) as live:
    for i in range(100):
        time.sleep(0.2)
        messages.append((time.asctime(), f'Event {i:03d}'))
        live.update(generate_table(messages))

【问题讨论】:

    标签: python rich


    【解决方案1】:

    我最近也在做同样的事情,也找不到内置的解决方案。由于您正在渲染实时显示,因此该表的行数不会超过 ~100 行,因此不必担心效率问题。

    这是我的解决方案。它反复从顶部删除行,直到表格适合为止。这是通过将表格放入 Layout 来衡量的,如果表格不合适,它会截断底部的表格。

    from collections import deque
    import os
    import time
    from rich.live import Live
    from rich.table import Table
    from rich.layout import Layout
    from rich.console import Console
    
    
    def generate_table(rows):
        layout = Layout()
        console = Console()
    
        table = Table()
        table.add_column('Time')
        table.add_column('Message')
    
        rows = list(rows)
    
        # This would also get the height:
        # render_map = layout.render(console, console.options)
        # render_map[layout].region.height
        n_rows = os.get_terminal_size()[1]
    
        while n_rows >= 0:
            table = Table()
            table.add_column('Time')
            table.add_column('Message')
    
            for row in rows[-n_rows:]:
                table.add_row(*row)
    
            layout.update(table)
    
            render_map = layout.render(console, console.options)
    
            if len(render_map[layout].render[-1]) > 2:
                # The table is overflowing
                n_rows -= 1
            else:
                break
    
        return table
    
    
    width, height = os.get_terminal_size()
    messages = deque(maxlen=height-4)  # save space for header and footer
    
    with Live(generate_table(messages), refresh_per_second=5) as live:
        for i in range(100):
            time.sleep(0.2)
            messages.append((time.asctime(), f'Event {i:03d}'))
            live.update(generate_table(messages))
    

    这里的魔法线是if len(render_map[layout].render[-1]) > 2:。 这是一种判断表格是否完整打印的方法。 如果是,render_map[layout].render 的最后一个元素会是这样的

    [
        Segment('└──────────────────────────┘', Style()),
        Segment('                                                                         ',)
    ]
    

    或喜欢

    [
        Segment(
            '
    ',
        )
    ]
    

    但如果它被截断,它将看起来像

    [
        Segment('│', Style()),
        Segment(' ', Style()),
        Segment(
            '37',
            Style(color=Color('cyan', ColorType.STANDARD, number=6), bold=True, italic=False)
        ),
        Segment('                      ', Style()),
        Segment(' ', Style()),
        Segment('│', Style()),
        Segment('                                                                         ',)
    ]
    

    【讨论】:

    • 这是一个聪明的解决方案。感觉有点hacky,但它确实解决了问题。而且由于它只使用 Rich 的公共 API,它看起来也很可靠/稳定。
    • 我同意这很hacky - 我想基本问题是Rich 事先不知道桌子会有多大。我猜想也存在更强大的解决方案,但基本思想仍然是“尝试渲染它并查看”。
    猜你喜欢
    • 1970-01-01
    • 2022-01-17
    • 2020-09-04
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 2020-05-09
    相关资源
    最近更新 更多