英文:
Textual: UI is not updating after change the value
问题
我尝试使用Python的textual
包构建一个基于TUI的简单应用程序。我有一个左侧面板,我想在其中显示项目列表,右侧面板上我想显示左侧面板中选定项目的详细信息。因此,我希望使用textual库提供的键绑定在左侧面板中添加项目,但当我向列表中添加新项目时,它不会更新左侧面板的UI,以显示新添加的项目。我正在遵循这个文档来添加该功能,但它不像预期的那样工作。我无法弄清楚这里出了什么问题,或者我的理解有误。
这是我的完整代码:
import uuid
from time import monotonic
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Button, Header, Footer, Static, ListView, ListItem, Label
class LeftPanel(Widget):
items = reactive([])
def compose(self) -> ComposeResult:
yield Static(
"All Request",
expand=True,
id="left_panel_header"
)
yield ListView(
*self.items,
initial_index=None,
)
class RightPanel(Widget):
"""A stopwatch widget."""
def compose(self) -> ComposeResult:
yield ListView(
ListItem(Label("4")),
ListItem(Label("5")),
ListItem(Label("6")),
initial_index=None,
)
class DebugApp(App):
"""A Textual app to manage stopwatches."""
CSS_PATH = "main.css"
BINDINGS = [
("d", "toggle_dark", "Toggle dark mode"),
("a", "add_item", "Add new item"),
]
def compose(self) -> ComposeResult:
"""Called to add widgets to the app."""
yield Container(LeftPanel(id="my_list"), id="left_panel")
yield Container(RightPanel(), id="right_panel")
yield Footer()
def action_add_item(self):
self.query_one("#my_list").items.append(ListItem(Label(str(uuid.uuid4()), classes="request_item"))
self.dark = not self.dark # This works
def action_toggle_dark(self) -> None:
"""An action to toggle dark mode."""
self.dark = not self.dark
def render_ui():
app = DebugApp(watch_css=True)
app.run()
如果您需要进一步的帮助,请随时告诉我。
<details>
<summary>英文:</summary>
I am trying to build a simple TUI based app using Python's `textual` package. I have one left panel where I want to display list of items and on right panel I wan to show details of the selected item from left panel. So I want add items in the left panel using keybinding provided by textual lib but when I add new item to the list it does not updates the UI of the left panel to show newly added item in the list. I am following this [doc][1]
[1]: https://textual.textualize.io/guide/reactivity/#__tabbed_2_1 to add that feature but it is not working as expected. I am not able to figure out what's wrong here or my understanding of the things are incorrect.
Here is my full code:
import uuid
from time import monotonic
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Button, Header, Footer, Static, ListView, ListItem, Label
class LeftPanel(Widget):
items = reactive([])
def compose(self) -> ComposeResult:
yield Static(
"All Request",
expand=True,
id="left_panel_header"
)
yield ListView(
*self.items,
initial_index=None,
)
class RightPanel(Widget):
"""A stopwatch widget."""
def compose(self) -> ComposeResult:
yield ListView(
ListItem(Label("4")),
ListItem(Label("5")),
ListItem(Label("6")),
initial_index=None,
)
class DebugApp(App):
"""A Textual app to manage stopwatches."""
CSS_PATH = "main.css"
BINDINGS = [
("d", "toggle_dark", "Toggle dark mode"),
("a", "add_item", "Add new item"),
]
def compose(self) -> ComposeResult:
"""Called to add widgets to the app."""
yield Container(LeftPanel(id="my_list"), id="left_panel")
yield Container(RightPanel(), id="right_panel")
yield Footer()
def action_add_item(self):
self.query_one("#my_list").items.append(ListItem(Label(str(uuid.uuid4()), classes="request_item")))
self.dark = not self.dark # This works
def action_toggle_dark(self) -> None:
"""An action to toggle dark mode."""
self.dark = not self.dark
def render_ui():
app = DebugApp(watch_css=True)
app.run()
</details>
# 答案1
**得分**: 2
这应该可以工作,如果你调用`ListView`实例的`.append`方法。为了实现这一点,你可以为它指定一个独立的ID:
```python
yield ListView(
*self.items,
initial_index=None,
id="my_list_LV"
)
然后使用以下代码:
# ...
def action_add_item(self):
self.query_one("#my_list_LV").append(ListItem(Label(str(uuid.uuid4()), classes="request_item"))
(我测试过,对我来说有效)。
英文:
It should work if you call the .append
method of the ListView
instance. To achieve this you can give it its own id:
yield = ListView(
*self.items,
initial_index=None,
id = "my_list_LV"
)
and then use
# ...
def action_add_item(self):
self.query_one("#my_list_LV").append(ListItem(Label(str(uuid.uuid4()), classes="request_item")))
(I tested this and it worked for me).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论