在文本应用中,回车键的绑定不起作用

前端开发 2026-07-11

我有一个 textual 应用,大致是这样的:

class ToDoApp(App):
    BINDINGS = [
        Binding(key="q", action="quit", description="Quit the app"),
        Binding(
            key="question_mark",
            action="help",
            description="Show help screen",
            key_display="?",
        ),
        Binding(key="n", action="new", description="New ToDo", show=True),
        Binding(key="d", action="delete", description="Delete ToDo", show=True),
        Binding(key="j", action="down", description="Scroll down", show=True),
        Binding(key="k", action="up", description="Scroll up", show=True),
        Binding(key="enter", action="select", description="Select", show=True),
    ]

...

    def action_select(self) -> None:
        if self.focused == OptionList:
            self.query_one(SelectionList).focus()

其他绑定都能工作,但不知为何 enter 绑定不起作用。调试时我发现它从不进入 action_select 函数。

可能是什么问题?

解决方案

我发现了两个问题:

  1. Enter 可能已经绑定到应用程序或小部件上,对新的绑定可能没有反应。与ChatGPT交流后,我发现它可能需要在 Binding 中使用 priority=True
Binding("enter", "select", "Select", priority=True)

文档:Binding.priority

  1. self.focused == OptionList 不起作用,它需要使用 isinstance()
if isinstance(self.focused, OptionList):
    self.query_one(SelectionList).focus()

完整可运行的代码:

from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.widgets import OptionList, SelectionList, Footer


class ToDoApp(App):
    BINDINGS = [
        Binding("q", "quit", "Quit", show=True),
        Binding("n", "new", "New ToDo", show=True),
        Binding("d", "delete", "Delete ToDo", show=True),
        Binding("j", "down", "Scroll down", show=True),
        Binding("k", "up", "Scroll up", show=True),
        # Binding("l", "select", "Select", show=True),  # to check if function is working
        Binding("enter", "select", "Select", show=True, priority=True),
    ]

    def compose(self) -> ComposeResult:
        yield OptionList("Task 1", "Task 2", "Task 3")
        yield SelectionList(("Done 1", 1), ("Done 2", 2))
        # yield Footer()

    def action_select(self) -> None:
        # if self.focused == OptionList:
        #    self.query_one(SelectionList).focus()

        if isinstance(self.focused, OptionList):
            self.query_one(SelectionList).focus()


if __name__ == "__main__":
    ToDoApp().run()

编辑:

似乎有一种更好的方法,在按下 enterOptionList 时就用 on_option_list_option_selectedOptionList 上运行代码(无需绑定)

这个函数接收 event,其中包含关于在 OptionList 上被按下的选项的信息 —— event.option -> Option('Task1')event.option_index -> 0

from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.widgets import OptionList, SelectionList, TextArea


class ToDoApp(App):
    BINDINGS = [
        Binding("q", "quit", "Quit", show=True),
        Binding("n", "new", "New ToDo", show=True),
        Binding("d", "delete", "Delete ToDo", show=True),
        Binding("j", "down", "Scroll down", show=True),
        Binding("k", "up", "Scroll up", show=True),
        # doesn't need to bind to `enter`
    ]

    def compose(self) -> ComposeResult:
        yield OptionList("Task 1", "Task 2", "Task 3")
        yield SelectionList(("Done 1", 1), ("Done 2", 2))
        yield TextArea()

    def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None:
        """Executed when you press `Enter` in `OptionList`"""

        text_area = self.query_one(TextArea)
        text_area.insert(
            f"--- selected ---\n{event.option=} | {event.option_index=} | {event.option_id=}\n{event.option_list.options=}\n"
        )

        if isinstance(self.focused, OptionList):
            self.query_one(SelectionList).focus()


if __name__ == "__main__":
    ToDoApp().run()

文档:OptionList.OptionSelected

在此输入图片描述

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。