peterbrittain / asciimatics

A cross platform package to do curses-like operations, plus higher level APIs and widgets to create text UIs and ASCII art animations
Apache License 2.0
3.62k stars 237 forks source link

Question: Why are Widgets not displayed? #333

Closed josipbudzaki closed 2 years ago

josipbudzaki commented 2 years ago

I'm trying to run a basic UI according to layouts in the doc, but the Widgets are not displayed (just getting blank screen):

from time import sleep
from asciimatics.screen import ManagedScreen
from asciimatics.widgets import Frame, Text, TextBox, Layout, Label, Button, PopUpDialog, Widget

def run():
    with ManagedScreen() as screen:
        frame = Frame(screen, 80, 20, has_border=False)
        layout = Layout([100], fill_frame=True)
        frame.add_layout(layout)
        layout.add_widget(Text("Name:", "name"))
        layout.add_widget(Text("Address:", "address"))
        layout.add_widget(Text("Phone number:", "phone"))
        layout.add_widget(Text("Email address:", "email"))
        layout.add_widget(TextBox(
            Widget.FILL_FRAME, "Notes:", "notes", as_string=True, line_wrap=True))
        frame.fix()
        screen.refresh()
        sleep(10)
run()

What am I doing wrong here?

peterbrittain commented 2 years ago

Your Frame is a sub-class of Effect and so like all Effects needs to be played by the Screen. Rather than calling screen.refresh() try calling screen.play(...) passing in the Scene that includes your Frame.

The sort of thing you need is in the sample code - e.g. here: https://github.com/peterbrittain/asciimatics/blob/c7accc93d3e9ead2337364f97d938340bbda1695/samples/forms.py#L224-L227

josipbudzaki commented 2 years ago

Thanks for the hint. For the sake of completeness, here's my solution:

from time import sleep
from asciimatics.scene import Scene
from asciimatics.screen import Screen, ManagedScreen
from asciimatics.widgets import Frame, Text, TextBox, Layout, Label, Button, PopUpDialog, Widget

class FormFrame(Frame):
    def __init__(self, screen):
        super(FormFrame, self).__init__(screen,
            int(screen.height // 3),
            screen.width // 2,
            y=0,
            has_border=True,
            can_scroll=True,
            name="Form Frame")
        layout = Layout([100], fill_frame=True)
        self.add_layout(layout)
        layout.add_widget(Text("Name:", "name"))
        layout.add_widget(Text("Address:", "address"))
        layout.add_widget(Text("Phone number:", "phone"))
        layout.add_widget(Text("Email address:", "email"))
        layout.add_widget(TextBox(
            Widget.FILL_FRAME, "Notes:", "notes", as_string=True, line_wrap=True))
        self.fix()
        # screen.refresh()
        # sleep(10)

def run(screen, scene):
    scenes = [Scene([FormFrame(screen)], -1)]

    screen.play(scenes, stop_on_resize=True, start_scene=scene, allow_int=True)

last_scene = None
Screen.wrapper(run, catch_interrupt=False, arguments=[last_scene])