动态更改urwid.MainLoop威德

2024-05-23 23:04:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在查看一段源于urwid的代码:

import urwid
from functools import partial
from random import randint

class State(object):

    def __init__(self, main_widget):
        self.main_widget = main_widget

def handle_keystroke(app_state, key):
        if key in ('q', 'Q'):
            raise urwid.ExitMainLoop()
        else:
            loop.widget = urwid.Filler(urwid.Button('new rand int:' + str(randint(0, 100))))

app_state = State(urwid.Filler(urwid.Button('original widget')))

callback = partial(handle_keystroke, app_state)

loop = urwid.MainLoop(app_state.main_widget, unhandled_input=callback)
loop.run()

并注意到loop在函数unhandled_input定义之前被引用。此外,它不是作为参数传递的,它只是按名称硬编码到函数中。1) 为什么这是可能的,以及:2)是否有更明确的替代方案?否则很难做到,因为存在loopapp_state和{}的循环依赖关系。在


Tags: fromimportselfloopappmaindefwidget
2条回答

我不确定您的示例代码中有多少表示原始代码,但看起来您可能想熟悉一下the technique of using urwid's custom widgets wrapping text widgets, as shown in the answer的示例小部件,该小部件每次显示一行文本内容。在

下面是一个编写类似于您提供的示例代码的示例,其设计更适合urwid和Python:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function, absolute_import, division
import urwid
from random import randint


class RandomNumberWidget(urwid.WidgetWrap):
    def __init__(self):
        self.random_number = None
        self.text_widget = urwid.Text(u'')
        super(RandomNumberWidget, self).__init__(self.text_widget)

    def roll(self):
        self.random_number = randint(0, 100)
        self.update()

    def update(self):
        """Update UI
        """
        if self.random_number is None:
            self.text_widget.set_text('No number set')
        else:
            self.text_widget.set_text('Random number: %s' % self.random_number)


class App(object):
    def __init__(self):
        self.random_number_widget = RandomNumberWidget()
        top_message = 'Press any key to get a random number, or q to quit\n\n\n'
        widget = urwid.Pile([
            urwid.Padding(urwid.Text(top_message),
                          'center', width=('relative', len(top_message))),
            self.random_number_widget,
        ])
        self.widget = urwid.Filler(widget, 'top')

    def play(self):
        self.random_number_widget.roll()

    def play_or_exit(self, key):
        if key in ('q', 'Q', 'esc'):
            raise urwid.ExitMainLoop()
        app.play()


if __name__ == '__main__':
    app = App()
    loop = urwid.MainLoop(app.widget, unhandled_input=app.play_or_exit)
    loop.run()

也取决于您实际想要做什么,让定制小部件响应键盘事件是有意义的,而不是在全局处理程序中执行所有操作(IMO,对于简单程序来说,这完全可以)。在

当python编译一个函数时,作为赋值目标的左侧变量被视为local,其余的都是全局变量。loop没有赋值,因此当python运行loop.widget = urwid.Filler(...)时,它知道{}不是一个局部变量,它将在模块的名称空间中查找名称。在

模块名称空间是动态的,因此只要loop = urwid.MainLoop(app_state.main_widget, unhandled_input=callback)在查找之前运行,loop就会被创建并正常工作。由于在loop.run()之前无法执行回调,因此将定义loop。在

这是独生子女和全球国家面临的典型风险之一。确保在使用资源之前创建资源并不总是容易的。在

相关问题 更多 >