Different Bindings on TabPanes #3026
-
I have TabbedContent on one screen. I have two TabPanes elements, and I want to display only two Bindings in the first TabPane, and all of them in the second. Is it possible to do it? I found the bind method, but I'm not sure if it's the right approach in this case. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
If I were to do this I'd probably make my own custom from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.widgets import TabbedContent, TabPane, Button, Footer
class BasePane(TabPane):
BINDINGS = [
Binding("f1", "something", "First thing"),
Binding("f2", "another_thing", "Second thing"),
]
class FirstPane(BasePane):
def compose(self) -> ComposeResult:
yield Button("This is the first pane")
class SecondPane(BasePane):
BINDINGS = [
Binding("f3", "one_more_thing", "Also this too")
]
def compose(self) -> ComposeResult:
yield Button("This is the second pane")
class TabbedContentBindings(App[None]):
def compose(self) -> ComposeResult:
with TabbedContent():
yield FirstPane("First")
yield SecondPane("Second")
yield Footer()
if __name__ == "__main__":
TabbedContentBindings().run() Of course, by default, you'd then need to implement the corresponding from dataclasses import dataclass
from textual import on
from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.message import Message
from textual.widgets import TabbedContent, TabPane, Button, Footer, Label
class BasePane(TabPane):
BINDINGS = [
Binding("f1", "invoke('the_f1_action')", "First thing"),
Binding("f2", "invoke('the_f2_action')", "Second thing"),
]
@dataclass
class TabPaneAction(Message):
action: str
def action_invoke(self, action: str) -> None:
self.post_message(self.TabPaneAction(action))
class FirstPane(BasePane):
def compose(self) -> ComposeResult:
yield Button("This is the first pane")
class SecondPane(BasePane):
BINDINGS = [
Binding("f3", "invoke('one_more_thing')", "Also this too"),
Binding("f4", "invoke('even_more')", "Yes more"),
Binding("f5", "invoke('that_is_enough')", "No more bindings please")
]
def compose(self) -> ComposeResult:
yield Button("This is the second pane")
class TabbedContentBindings(App[None]):
def compose(self) -> ComposeResult:
yield Label("The pressed binding will appear here")
with TabbedContent():
yield FirstPane("First")
yield SecondPane("Second")
yield Footer()
@on(BasePane.TabPaneAction)
def perform_action(self, event: BasePane.TabPaneAction) -> None:
# Here we'd treat event.action as some sort of ID to work off.
self.query_one(Label).update(f"We've been asked to run a {event.action}")
if __name__ == "__main__":
TabbedContentBindings().run() Keep in mind of course that this might be slightly overkill if the common bindings are going to be common to all widgets on the screen, even outside of the Note also that there's another option, where if you want a common set of bindings available if you're in the |
Beta Was this translation helpful? Give feedback.
If I were to do this I'd probably make my own custom
TabPane
class for each of the panes that need the different bindings. Also, if there's a common set of bindings, I'd probably implement them in a base class for the other panes. For example: