Python: urwid: trying to handle different views

I am trying to write a program with different views.

I tried to create a class that handles different views using urwid, and also separate the view code from the rest. But after many different attempts, I do not know where to start.

What urwid objects do i need to cleanly remove and redraw the screen? And how do they need to be encapsulated so that I can switch views after user input?

+4
source share
1 answer

From Urwid Documentation :

The topmost widget displayed by MainLoop should be passed as the first parameter to the constructor. If you want to change the topmost widget while you work, you can assign a new widget to MainLoop objects. MainLoop.widget attribute. This is useful for applications that have a number of different modes or types.

Now for some code:

import urwid # This function handles input not handled by widgets. # It passed into the MainLoop constructor at the bottom. def unhandled_input(key): if key in ('q','Q'): raise urwid.ExitMainLoop() if key == 'enter': try: ## This is the part you're probably asking about loop.widget = next(views).build() except StopIteration: raise urwid.ExitMainLoop() # A class that is used to create new views, which are # two text widgets, piled, and made into a box widget with # urwid filler class MainView(object): def __init__(self,title_text,body_text): self.title_text = title_text self.body_text = body_text def build(self): title = urwid.Text(self.title_text) body = urwid.Text(self.body_text) body = urwid.Pile([title,body]) fill = urwid.Filler(body) return fill # An iterator consisting of 3 instantiated MainView objects. # When a user presses Enter, since that particular key sequence # isn't handled by a widget, it gets passed into unhandled_input. views = iter([ MainView(title_text='Page One',body_text='Lorem ipsum dolor sit amet...'), MainView(title_text='Page Two',body_text='consectetur adipiscing elit.'), MainView(title_text='Page Three',body_text='Etiam id hendrerit neque.') ]) initial_view = next(views).build() loop = urwid.MainLoop(initial_view,unhandled_input=unhandled_input) loop.run() 

In short, I used the global key processing function to listen to a specific sequence pressed by the user, and upon receiving this sequence my key processing function creates a new view object with the MainView class and replaces loop.widget with this object. Of course, in a real application, you will want to create a signal handler for a specific widget in your view class, and not use the global unhandled_input function for all user inputs. You can read about connect_signal function here .

Pay attention to the part about garbage collection in the signal documentation: if you are going to write something with many views, they will remain in memory even after you replace them due to the fact that signal_handler is a closure that implicitly refers to this the widget, so you need to pass the weak_args named argument to the weak_args function to tell Urwid to leave if it is not actively used in the event loop.

+3
source

Source: https://habr.com/ru/post/1501357/


All Articles