Skip to content

tuiapp_v2: AttributeError: 'Screen' object has no attribute '_select_start' — 兼容 Textual >= 8.x #373

@guowenjiao54

Description

@guowenjiao54

问题描述

运行 tuiapp_v2.py 时报错:

AttributeError: 'Screen' object has no attribute '_select_start'

出错代码位置

frontends/tuiapp_v2.py 第 828-829 行_patch_auto_scroll_for_selection 方法):

if screen._select_start is not None:       # ← L828
    sw = screen._select_start[0]           # ← L829

环境

  • OS: Linux-5.15.0-173-generic-x86_64-with-glibc2.35
  • Python: 3.10.12 (main, Mar 3 2026, 11:56:32) [GCC 11.4.0]
  • Textual: 8.2.6
  • Arch: x86_64

根因分析

screen._select_startTextual Screen 类的私有 API,在旧版(约 0.x 系列)中是一个 tuple[Widget, Offset] 类型属性,记录选区起始位置。

但在 Textual 8.2.6 中,_select_start 已被完全移除。搜索整个 Textual 代码库均无此属性。

新版 Textual 改用 _select_state: Reactive[SelectState | None] 架构:

_select_state → SelectState(NamedTuple):
    ├── start: SelectStart
    │   ├── container: Widget
    │   ├── container_pointer_delta: Offset
    │   ├── container_initial_offset: Offset
    │   ├── container_initial_scroll_offset: Offset
    │   ├── content_widget: Widget | None
    │   └── content_offset: Offset | None
    └── end: SelectEnd | None

修复建议

将 L828-L831 替换为:

sw = None
if hasattr(screen, '_select_state') and screen._select_state is not None:
    start = screen._select_state.start
    if start is not None:
        sw = start.content_widget or start.container
if sw is not None and sw is not select_widget:
    candidates.append(sw)

或者更简单的版本(仅向下兼容):

sw = getattr(screen, '_select_start', None)
if sw is not None:
    sw = sw[0]  # tuple[Widget, Offset]
elif hasattr(screen, '_select_state'):
    sw = screen._select_state.start.content_widget if screen._select_state and screen._select_state.start else None
if sw is not None and sw is not select_widget:
    candidates.append(sw)

备注

  • _select_start_select_state 都是 Textual 的私有 API,不保证跨版本兼容
  • 长期稳妥方案:上游 Textual 若提供公开的选区起始位置 API,应改用公共接口

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions