npyscreen简单应用(二)- NPSAppManaged

程序结构

npyscreen应用主要由表单(Form Object)、表单部件(Widget Object)和应用对象(Application Objects)组成。

  • Widget Object: Input,CheckBox,Radio,SlideBar等表单组件。
  • Form Object: Widgetght的容器,表单尺寸通常为控制台的尺寸。
  • Application: Application提供管理应用环境的便捷方法, 可以减少多屏幕程序在交互时可能出现的错误,并且在开发时可以通过此对象使用npyscreen提供的附加特性。
import npyscreen

# Application Object
class MyTestApp(npyscreen.NPSAppManaged):
    def onStart(self):
        self.registerForm("MAIN", MainForm())

# Form 表单对象
class MainForm(npyscreen.Form):
    def create(self):
        # weight 对象
        self.add(npyscreen.TitleText, name = "Text:", value= "Hellow World!" )

    def afterEditing(self):
        self.parentApp.setNextForm(None)

if __name__ == '__main__':
    TA = MyTestApp()
    TA.run()

如果觉得上面的代码对于创建一个应用程序太繁琐了,npyscreen的作者为我们提供了另一种更为简便的方式来创建程序。

import npyscreen

# 使用函数代替class来创建Form对象
def myFunction(*args):
    F = npyscreen.Form(name='My Test Application') 
    # 在Form中添加一个文本输入框, 并在外面接收输入框的值
    wd = F.add_widget(npyscreen.TitleText, name = "Text:", value= "Hello World!" )
    # F.edit() 在执行时,在显示交互界面后会等待用户操作后,再返回wd的值;而使用F.display()时,程序会直接获取运行并输出wd的值
    F.edit()
    return wd.value

if __name__ == '__main__':
    # 使用npyscreen的warpper构建应用程序
    retVal = npyscreen.wrapper_basic(myFunction)
    print(retVal)

面向对象

虽然npyscreen提供的wrapper可以很轻松的创建简单程序,但当Form对象中包含众多Widget时,我们就需要自定义一个Form对象来统一管理Widget。
想要创建自定义的Form对象,只需要继承npyscreen.Form,然后重写create方法即可。

class CustomForm(npyscreen.Form):
    def create(self):
        self.name = self.add(npyscreen.TitleText, name='Name')
        self.age  = self.add(npyscreen.TitleText, name='Age')
        self.date = self.add(npyscreen.TitleDateCombo, name='Date')

在上面的例子中,我们了解了如何自定义Form对象来管理我们的页面部件,但在程序中仍然需要我们手动去调用edit方法来显示页面。这样的调用方式不但不够优雅,还容易引发深度递归的问题。接下来我们来看看如何使用NPSAppManaged类来管理程序中的Form(NPSAppManaged是管理应用程序的最佳方式),使用NPSAppManaged时,不需要像普通的NPSApp那样编写自定义主循环,NPSAppManaged将自主管理程序中的每个Form,用户只需要调用run方法即可。

class MyApplication(npyscreen.NPSAppManaged):
    def onStart(self):
        self.addForm('MAIN', CustomForm, name='New Form')

NPSAppManaged使用MAIN Form作程序入口,使用NPSAppManaged管理程序时一定要指定MAIN对应的Form,否则会抛出self._LAST_NEXT_ACTIVE_FORM = self._Forms[self.NEXT_ACTIVE_FORM] KeyError: 'MAIN'异常。

NPSAppManaged

注册Form

NPSAppManaged提供了三种注册Form的方法

# 方法一
NPSAppManaged.addForm(*id*, *FormClass*, ...)
# 方法二
NPSAppManaged.addFormClass(*id*, *FormClass* ...)
# 方法三
NPSAppManaged.registerForm(id, fm)

addForm方法

NPSAppManaged.addForm(*id*, *FormClass*, ...)方法的参数列表中,id接收一个字符串作为Form的唯一标识,FormClass接收一个Form类,由addForm方法创建一个Form的实例,并返回该Form实例的弱引用。而多余的参数将作为Form类构造函数的参数。

addFormClass方法

NPSAppManaged.addFormClass(*id*, *FormClass*, ...), 这个方法传入的参数与addForm方法相同,方法接收一个Form Class做参数,多余的参数传入Form的构造函数。而此方法与addForm方法的区别在于,每次被编辑时都是创建一个新的Form实例。

registerForm方法

NPSAppManaged.registerForm(id, fm)方法与上面两个方法都不同,它接收的参数是一个Form的实例,并将这个实例注册到NPSAppManaged管理的Form集合中。这里需要注意一下,registerForm只有两个参数,因为Form实例在方法前已经实例化了,这里就不再接收和创建Form相关的参数。

通过以上三种方法创建的Form实例都可以通过self.parentApp来获取到NPSAppManaged对象,如果想要移除Form,可以调用removeForm(id)方法。

运行Application

通过前面的方法,我们已经能够创建并注册自定义的Form对象到NPSAppManaged应用中,接下来只要调用NPSAppManaged.run()方法就可以让程序运行起来了,如果你运行之后发现出现了self._LAST_NEXT_ACTIVE_FORM = self._Forms[self.NEXT_ACTIVE_FORM] KeyError: 'MAIN',别急,那可能是我忘记告诉你设置程序的初始Form了。

NPSAppManaged.run()执行时,会默认将Form id为‘MAIN’的Form作为初始Form显示在界面内,如果没有正确的设置‘MAIN’Form,就会出现类似上面提到的异常情况。当然,如果你不想使用‘MAIN’作为初始Form的id名称,可以在调用run方法前修改NPSAppManaged.STARTING_FORM的值,来指定初始Form的id。

现在重新执行run方法应该就可以成功的运行程序了,当然现在我们的程序只有一个Form,太简陋,读者可以试着多创建几个Form,通过下列方法去按自己的方式控制程序显示。

方法名 说明
NPSAppManaged.setNextForm(formid) 设置下一个显示的Form
NPSAppManaged.setNextFormPrevious() 将当前Form的上一个Form设置为下一个显示
NPSAppManaged.switchForm(formid) 切换到指定Form
NPSAppManaged.switchFormPrevious() 切换到指定Form的上一个Form

如果setNextFormswitchForm传入参数为None,则退出程序

NPSAppManaged 生命周期函数

用于通过通过重写NPSAppManaged的部分方法来控制NPSAppManaged的生命周期

方法 说明
NPSAppManaged.onInMainLoop() 在每个屏幕之间切换时调用(首屏不会调用)
NPSAppManaged.onStart() 初始化方法,可以在这里设置Form
NPSAppManaged.onCleanExit() 程序正常退出时调用此方法
Form.beforeEditing() 在Form初始前执行
Form.afterEditing() 在退出Form时执行

完整代码

import npyscreen


class CustomForm(npyscreen.Form):
    def create(self):
        self.name = self.add(npyscreen.TitleText, name='Name')
        self.age = self.add(npyscreen.TitleText, name='Age')
        self.date = self.add(npyscreen.TitleDateCombo, name='Date')
        self.myDepartment = self.add(npyscreen.TitleSelectOne, max_height=3,
                                     name='Department',
                                     values=['Option 1', 'Option 2', 'Option 3'],
                                     scroll_exit=True)
        # scroll_exit True 方向键上下超过可选数量时, 会直接切换到上一个或下一个Widget
        # false 时, 只能通过tab切换widget
    
    def afterEditing(self):
        self.parentApp.addForm('SecondForm', CustomSecondForm, name='Second Form')
        self.parentApp.setNextForm('SecondForm')


class CustomSecondForm(npyscreen.Form):
    def create(self):
        self.info = self.add(npyscreen.TitleText, value="Second Form")

    def afterEditing(self):
        # self.parentApp.setNextFormPrevious()
        self.parentApp.setNextForm(None)


class MyApplication(npyscreen.NPSAppManaged):
    def onStart(self):
        self.addForm('MAIN', CustomForm, name='First Form')
        # self.addForm(MyApplication.STARTING_FORM, CustomForm, name='New Form')

    def onInMainLoop(self):
        print('onInMainLoop')
        super().onInMainLoop()

    def onCleanExit(self):
        print('onCleanExit')
        super().onCleanExit()


if __name__ == '__main__':
    # 设置自定义的初始Form id, 设置后, 'MAIN'将无法使用
    # MyApplication.STARTING_FORM = 'MyMain'
    TestApp = MyApplication().run()
    print("Application Exit")

你可能感兴趣的:(npyscreen简单应用(二)- NPSAppManaged)