feat: 新增技能扩展N15一章相关示例源码

This commit is contained in:
100gle
2023-03-09 09:43:45 +08:00
parent ed1a7eb61d
commit e963474669
6 changed files with 286 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
from textual.app import App
class SimpleApp(App):
pass
if __name__== '__main__':
app = SimpleApp()
app.run()

View File

@@ -0,0 +1,70 @@
import re
from textwrap import dedent
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.reactive import reactive
from textual.widgets import Footer, Header, Static
lorem = """\
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed eget suscipit ligula.
Curabitur id justo imperdiet, pretium orci sed, tempus leo.
Integer vulputate vitae diam efficitur tempus.
Donec vel est ac purus feugiat ultricies sit amet non sapien.
Vivamus faucibus viverra bibendum.
Integer congue sed mi et imperdiet. Praesent quis dapibus neque.
Cras arcu purus, laoreet eu nibh scelerisque, bibendum tincidunt mauris.
Cras congue erat leo, non efficitur tellus auctor a.
"""
class LoremWidget(Static):
is_highlight = reactive(False, layout=True)
_RE_LOREM = re.compile("(?P<target>Lorem ipsum)", re.I)
_cache_lorem = None
_raw_lorem = dedent(lorem)
def on_mount(self) -> None:
self.update(self._raw_lorem)
async def watch_is_highlight(self, old_value, new_value) -> None:
if self.is_highlight:
content = self.marked_lorem()
self.update(content)
else:
self.update(self._raw_lorem)
def marked_lorem(self):
if self._cache_lorem:
return self._cache_lorem
content = self._RE_LOREM.sub(r"[u red b]\1[/]", lorem)
self._cache_lorem = content
return content
class SimpleApp(App):
BINDINGS = [
("h", "highlight", "Highlight lorem"),
("q", "quit", "Quit"),
]
def compose(self) -> ComposeResult:
yield Header()
yield Container(LoremWidget(id="lorem"))
yield Footer()
def action_highlight(self) -> None:
widget = self.query_one("#lorem")
widget.is_highlight = not widget.is_highlight
def action_quit(self) -> None:
self.exit(0)
if __name__ == '__main__':
app = SimpleApp()
app.run()

View File

@@ -0,0 +1,74 @@
import re
from textwrap import dedent
from textual import events
from textual.app import App, ComposeResult
from textual.containers import Container
from textual.reactive import reactive
from textual.widgets import Footer, Header, Static
lorem = """\
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed eget suscipit ligula.
Curabitur id justo imperdiet, pretium orci sed, tempus leo.
Integer vulputate vitae diam efficitur tempus.
Donec vel est ac purus feugiat ultricies sit amet non sapien.
Vivamus faucibus viverra bibendum.
Integer congue sed mi et imperdiet. Praesent quis dapibus neque.
Cras arcu purus, laoreet eu nibh scelerisque, bibendum tincidunt mauris.
Cras congue erat leo, non efficitur tellus auctor a.
"""
class LoremWidget(Static):
is_highlight = reactive(False, layout=True)
_RE_LOREM = re.compile("(?P<target>Lorem ipsum)", re.I)
_cache_lorem = None
_raw_lorem = dedent(lorem)
def on_mount(self) -> None:
self.update(self._raw_lorem)
async def watch_is_highlight(self, old_value, new_value) -> None:
if self.is_highlight:
content = self.marked_lorem()
self.update(content)
else:
self.update(self._raw_lorem)
def marked_lorem(self):
if self._cache_lorem:
return self._cache_lorem
content = self._RE_LOREM.sub(r"[u red b]\1[/]", lorem)
self._cache_lorem = content
return content
class SimpleApp(App):
def compose(self) -> ComposeResult:
yield Header()
yield Container(LoremWidget(id="lorem"))
yield Footer()
def on_key(self, event: events.Key) -> None:
if event.key == "h":
self.action_highlight()
elif event.key == "q":
self.action_quit()
elif event.key == "d":
self.action_toggle_dark()
def action_highlight(self) -> None:
widget = self.query_one("#lorem")
widget.is_highlight = not widget.is_highlight
def action_quit(self) -> None:
self.exit(0)
if __name__ == '__main__':
app = SimpleApp()
app.run()

View File

@@ -0,0 +1,62 @@
from textual import events
from textual.app import App
from textual.containers import Container
from textual.widgets import Static
class ClickableColorBlock(Static):
background_toggled = False
raw_background = ""
def on_mount(self):
self.styles.border = ("heavy", "white")
self.raw_background = self.styles.background
def on_click(self, event: events.Click):
event.prevent_default()
self.background_toggled = not self.background_toggled
self.styles.background = (
str(self.render()) if self.background_toggled else self.raw_background
)
self.log("block background changed!")
class DisplayApp(App):
CSS_PATH = "css/events.css"
background_toggled = False
def compose(self):
yield Container(
ClickableColorBlock("red", classes="block"),
ClickableColorBlock("blue", classes="block"),
ClickableColorBlock("green", classes="block"),
ClickableColorBlock("cyan", classes="block"),
id="display-container",
)
def on_click(self):
self.background_toggled = not self.background_toggled
target = self.query_one("#display-container")
blocks = target.query(".block")
background = None
border = None
if self.background_toggled:
background = "white"
border = ("heavy", "black")
else:
background = "grey"
border = ("heavy", "white")
target.styles.background = background
for block in blocks:
block.styles.border = border
self.log("container background changed!")
if __name__ == '__main__':
app = DisplayApp()
app.run()

View File

@@ -0,0 +1,55 @@
from textual.app import App
from textual.containers import Vertical
from textual.reactive import reactive
from textual.widget import Widget
from textual.widgets import Input
class WelcomeWidget(Widget):
who = reactive("World!")
total = reactive(15)
def on_mount(self):
default_styles = """
margin: 1;
padding: 1;
"""
self.set_styles(default_styles)
def render(self):
return f":partying_face: Hello, [b red]{self.who}[/]! ({self.total}/15)"
def watch_who(self, old_value, new_value):
self.log(
f"who attribute changed: old value: {old_value}, "
f"new value: {new_value} "
)
def compute_total(self):
return len(self.who)
class InputChangeApp(App):
def compose(self):
yield Vertical(
Input(placeholder="enter your name..."),
WelcomeWidget(classes="welcome"),
)
def on_input_changed(self, event: Input.Changed) -> None:
target = self.query_one(".welcome")
value = event.value
if len(value) > 15:
event.input.value = value[:15]
return
if not value:
target.who = "World!"
else:
target.who = value
if __name__ == '__main__':
app = InputChangeApp()
app.run()

View File

@@ -0,0 +1,16 @@
#display-container {
layout: grid;
grid-size: 2 2;
align: center middle;
background: grey;
border: solid white;
margin: 1;
height: 100%;
}
.block {
content-align: center middle;
width: 100%;
margin: 2;
}