Python:urwid:尝试处理不同的视图

时间:2013-09-09 19:44:31

标签: python model-view-controller view urwid

我正在尝试编写一个具有不同视图的程序。

我尝试创建一个用urwid处理不同视图的类,同时将视图代码与其余视图代码分开。但经过多次尝试后,我不知道从哪里开始了。

我需要哪些urwid对象来进行干净的擦除和重绘屏幕?它们如何封装,以便我可以在用户输入后切换视图?

1 个答案:

答案 0 :(得分:3)

来自Urwid documentation

  

MainLoop显示的最顶部窗口小部件必须作为第一个传递   构造函数的参数。   如果您想要更改最顶层的小部件   在运行时,您可以为MainLoop对象分配一个新的小部件   MainLoop.widget属性。这对于拥有a的应用程序很有用   不同模式或观点的数量。

现在有些代码:

import urwid

# This function handles input not handled by widgets.
# It's 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()

简而言之,我使用全局键处理函数来侦听用户按下的某个序列,并在接收到该序列时,我的键处理函数使用MainView类构建一个新的视图对象并替换{{1}用那个对象。当然,在实际应用程序中,您将要在视图类中的特定窗口小部件上创建信号处理程序,而不是对所有用户输入使用全局unhandled_input函数。您可以阅读connect_signal函数here

注意信号函数文档中关于垃圾收集的部分:如果你打算用很多视图写一些东西,那么即使在你替换它们之后它们也会保留在内存中,因为signal_handler是一个闭包,隐式地保留对该窗口小部件的引用,因此您需要将loop.widget命名参数传递给weak_args函数,以告知Urwid在事件循环中没有主动使用它时让它继续运行。