首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实时显示中表格的垂直溢出应滚动内容

实时显示中表格的垂直溢出应滚动内容
EN

Stack Overflow用户
提问于 2021-02-24 16:46:59
回答 1查看 1.1K关注 0票数 4

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

代码语言:javascript
复制
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'的行为,右边部分显示所需的行为:

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

代码语言:javascript
复制
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))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-29 13:26:38

我最近也在做同样的事情,也找不到一个内置的解决方案。由于您正在呈现一个活动显示,该表的行数不会超过100行,因此不应该考虑效率问题。

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

代码语言:javascript
复制
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的最后一个元素如下所示

代码语言:javascript
复制
[
    Segment('└──────────────────────────┘', Style()),
    Segment('                                                                         ',)
]

或者像这样

代码语言:javascript
复制
[
    Segment(
        '
',
    )
]

但是如果它被截断了,它看起来就像

代码语言:javascript
复制
[
    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('                                                                         ',)
]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66355239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档