docs/FAQ.md
Welcome to the Textual FAQ. Here we try and answer any question that comes up frequently. If you can't find what you are looking for here, see our other help channels.
<a name="does-textual-support-images"></a>
Textual doesn't have built-in support for images yet, but it is on the Roadmap.
See also the rich-pixels project for a Rich renderable for images that works with Textual.
<a name="how-can-i-fix-importerror-cannot-import-name-composeresult-from-textualapp-"></a>
You likely have an older version of Textual. You can install the latest version by adding the -U switch which will force pip to upgrade.
The following should do it:
pip install textual-dev -U
<a name="how-can-i-select-and-copy-text-in-a-textual-app"></a>
Textual supports text selection for most widgets, via click and drag. Press ctrl+c to copy.
For widgets that don't yet support text selection, you can try and use your terminal's builtin support. Most terminal emulators offer a modifier key which you can hold while you click and drag to restore the behavior you may expect from the command line. The exact modifier key depends on the terminal and platform you are running on.
Refer to the documentation for your terminal emulator, if it is not listed above.
<a name="how-can-i-set-a-translucent-app-background"></a>
Some terminal emulators have a translucent background feature which allows the desktop underneath to be partially visible.
This feature is unlikely to work with Textual, as the translucency effect requires the use of ANSI background colors, which Textual doesn't use. Textual uses 16.7 million colors where available which enables consistent colors across all platforms and additional effects which aren't possible with ANSI colors.
For more information on ANSI colors in Textual, see Why no ANSI Themes?.
<a name="how-do-i-center-a-widget-in-a-screen"></a>
!!! tip
See [*How To Center Things*](https://textual.textualize.io/how-to/center-things/) in the
Textual documentation for a more comprehensive answer to this question.
To center a widget within a container use
align. But remember that
align works on the children of a container, it isn't something you use
on the child you want centered.
For example, here's an app that shows a Button in the middle of a
Screen:
from textual.app import App, ComposeResult
from textual.widgets import Button
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Button("PUSH ME!")
if __name__ == "__main__":
ButtonApp().run()
If you use the above on multiple widgets, you'll find they appear to "left-align" in the center of the screen, like this:
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
If you want them more like this:
+-----+
| |
+-----+
+---------+
| |
+---------+
+---------------+
| |
+---------------+
The best approach is to wrap each widget in a Center
container
that individually centers it. For example:
from textual.app import App, ComposeResult
from textual.containers import Center
from textual.widgets import Button
class ButtonApp(App):
CSS = """
Screen {
align: center middle;
}
"""
def compose(self) -> ComposeResult:
yield Center(Button("PUSH ME!"))
yield Center(Button("AND ME!"))
yield Center(Button("ALSO PLEASE PUSH ME!"))
yield Center(Button("HEY ME ALSO!!"))
if __name__ == "__main__":
ButtonApp().run()
<a name="how-do-i-fix-workerdeclarationerror"></a>
Textual version 0.31.0 requires that you set thread=True on the @work decorator if you want to run a threaded worker.
If you want a threaded worker, you would declare it in the following way:
@work(thread=True)
def run_in_background():
...
If you don't want a threaded worker, you should make your work function async:
@work()
async def run_in_background():
...
This change was made because it was too easy to accidentally create a threaded worker, which may produce unexpected results.
<a name="how-do-i-pass-arguments-to-an-app"></a>
When creating your App class, override __init__ as you would when
inheriting normally. For example:
from textual.app import App, ComposeResult
from textual.widgets import Static
class Greetings(App[None]):
def __init__(self, greeting: str="Hello", to_greet: str="World") -> None:
self.greeting = greeting
self.to_greet = to_greet
super().__init__()
def compose(self) -> ComposeResult:
yield Static(f"{self.greeting}, {self.to_greet}")
Then the app can be run, passing in various arguments; for example:
# Running with default arguments.
Greetings().run()
# Running with a keyword argument.
Greetings(to_greet="davep").run()
# Running with both positional arguments.
Greetings("Well hello", "there").run()
<a name="why-do-some-key-combinations-never-make-it-to-my-app"></a>
Textual can only ever support key combinations that are passed on by your terminal application. Which keys get passed on can differ from terminal to terminal, and from operating system to operating system.
Because of this it's best to stick to key combinations that are known to be universally-supported; these include the likes of:
When creating bindings for your application we recommend picking keys and key combinations from the above.
Keys that aren't normally passed through by terminals include Cmd and Option on macOS, and the Windows key on Windows.
If you need to test what key
combinations
work in different environments you can try them out with textual keys.
<a name="why-doesnt-textual-look-good-on-macos"></a>
You may find that the default macOS Terminal.app doesn't render Textual apps (and likely other TUIs) very well, particularly when it comes to box characters. For instance, you may find it displays misaligned blocks and lines like this:
You can (mostly) fix this by opening settings -> profiles > Text tab, and changing the font settings. We have found that Menlo Regular font, with a character spacing of 1 and line spacing of 0.805 produces reasonable results. If you want to use another font, you may have to tweak the line spacing until you get good results.
With these changes, Textual apps render more as intended:
Even with this fix, Terminal.app has a few limitations. It is limited to 256 colors, and can be a little slow compared to more modern alternatives. Fortunately there are a number of free terminal emulators for macOS which produces high quality results.
We recommend any of the following terminals:
<a name="why-doesnt-textual-support-ansi-themes"></a>
Textual will not generate escape sequences for the 16 themeable ANSI colors.
This is an intentional design decision we took for the following reasons:
Textual has a design system which guarantees apps will be readable on all platforms and terminals, and produces better results than ANSI colors.
There is currently a light and dark version of the design system, but more are planned. It will also be possible for users to customize the source colors on a per-app or per-system basis. This means that in the future you will be able to modify the core colors to blend in with your chosen terminal theme.
!!! tip "Changed in version 0.80.0"
Textual added an `ansi_color` boolean to App. If you set this to `True`, then Textual will not attempt to convert ANSI colors. Note that you will lose transparency effects if you enable this setting.
Generated by FAQtory