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

4

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

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

为了清除屏幕并重新绘制,我需要哪些urwid对象?它们需要如何封装,以便在用户输入后切换视图?

1个回答

4

来自Urwid文档

MainLoop显示的最上层的小部件必须作为构造函数的第一个参数传递。 如果你想在运行时更改最上层的小部件,可以将一个新的小部件分配给MainLoop对象的MainLoop.widget属性。这对于具有多种模式或视图的应用程序非常有用。

现在是一些代码:

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类构建一个新的视图对象,并将loop.widget替换为该对象。当然,在实际应用中,您需要在视图类中的特定小部件上创建一个信号处理程序,而不是为所有用户输入使用全局未处理输入功能。您可以在这里阅读有关connect_signal函数的信息。
请注意Signal Functions文档中有关垃圾回收的部分:如果您打算编写具有多个视图的内容,则它们将保留在内存中,即使在替换它们后也是如此,因为signal_handler是一个闭包,它隐式地保留对该小部件的引用,因此您需要将weak_args命名参数传递给urwid.connect_signal函数,以告诉Urwid在事件循环中不再使用时释放它。

2
不错的例子!我认为这种方法适用于当您拥有不同模式并需要在它们之间切换时。对于实际实现类似此处的阅读应用程序,可能更好的是使用自定义小部件来显示每个页面--您已经提到了内存影响,但还是提一下。 =D - Elias Dorneles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接