npyscreen簡(jiǎn)單應(yīng)用(二)- NPSAppManaged

程序結(jié)構(gòu)

npyscreen應(yīng)用主要由表單(Form Object)、表單部件(Widget Object)和應(yīng)用對(duì)象(Application Objects)組成。

  • Widget Object: Input,CheckBox,Radio,SlideBar等表單組件。
  • Form Object: Widgetght的容器,表單尺寸通常為控制臺(tái)的尺寸。
  • Application: Application提供管理應(yīng)用環(huán)境的便捷方法, 可以減少多屏幕程序在交互時(shí)可能出現(xiàn)的錯(cuò)誤,并且在開(kāi)發(fā)時(shí)可以通過(guò)此對(duì)象使用npyscreen提供的附加特性。
import npyscreen

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

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

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

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

如果覺(jué)得上面的代碼對(duì)于創(chuàng)建一個(gè)應(yīng)用程序太繁瑣了,npyscreen的作者為我們提供了另一種更為簡(jiǎn)便的方式來(lái)創(chuàng)建程序。

import npyscreen

# 使用函數(shù)代替class來(lái)創(chuàng)建Form對(duì)象
def myFunction(*args):
    F = npyscreen.Form(name='My Test Application') 
    # 在Form中添加一個(gè)文本輸入框, 并在外面接收輸入框的值
    wd = F.add_widget(npyscreen.TitleText, name = "Text:", value= "Hello World!" )
    # F.edit() 在執(zhí)行時(shí),在顯示交互界面后會(huì)等待用戶操作后,再返回wd的值;而使用F.display()時(shí),程序會(huì)直接獲取運(yùn)行并輸出wd的值
    F.edit()
    return wd.value

if __name__ == '__main__':
    # 使用npyscreen的warpper構(gòu)建應(yīng)用程序
    retVal = npyscreen.wrapper_basic(myFunction)
    print(retVal)

面向?qū)ο?/h1>

雖然npyscreen提供的wrapper可以很輕松的創(chuàng)建簡(jiǎn)單程序,但當(dāng)Form對(duì)象中包含眾多Widget時(shí),我們就需要自定義一個(gè)Form對(duì)象來(lái)統(tǒng)一管理Widget。
想要?jiǎng)?chuàng)建自定義的Form對(duì)象,只需要繼承npyscreen.Form,然后重寫(xiě)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對(duì)象來(lái)管理我們的頁(yè)面部件,但在程序中仍然需要我們手動(dòng)去調(diào)用edit方法來(lái)顯示頁(yè)面。這樣的調(diào)用方式不但不夠優(yōu)雅,還容易引發(fā)深度遞歸的問(wèn)題。接下來(lái)我們來(lái)看看如何使用NPSAppManaged類(lèi)來(lái)管理程序中的Form(NPSAppManaged是管理應(yīng)用程序的最佳方式),使用NPSAppManaged時(shí),不需要像普通的NPSApp那樣編寫(xiě)自定義主循環(huán),NPSAppManaged將自主管理程序中的每個(gè)Form,用戶只需要調(diào)用run方法即可。

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

NPSAppManaged使用MAIN Form作程序入口,使用NPSAppManaged管理程序時(shí)一定要指定MAIN對(duì)應(yīng)的Form,否則會(huì)拋出self._LAST_NEXT_ACTIVE_FORM = self._Forms[self.NEXT_ACTIVE_FORM] KeyError: 'MAIN'異常。

NPSAppManaged

注冊(cè)Form

NPSAppManaged提供了三種注冊(cè)Form的方法

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

addForm方法

NPSAppManaged.addForm(*id*, *FormClass*, ...)方法的參數(shù)列表中,id接收一個(gè)字符串作為Form的唯一標(biāo)識(shí),FormClass接收一個(gè)Form類(lèi),由addForm方法創(chuàng)建一個(gè)Form的實(shí)例,并返回該Form實(shí)例的弱引用。而多余的參數(shù)將作為Form類(lèi)構(gòu)造函數(shù)的參數(shù)。

addFormClass方法

NPSAppManaged.addFormClass(*id*, *FormClass*, ...), 這個(gè)方法傳入的參數(shù)與addForm方法相同,方法接收一個(gè)Form Class做參數(shù),多余的參數(shù)傳入Form的構(gòu)造函數(shù)。而此方法與addForm方法的區(qū)別在于,每次被編輯時(shí)都是創(chuàng)建一個(gè)新的Form實(shí)例。

registerForm方法

NPSAppManaged.registerForm(id, fm)方法與上面兩個(gè)方法都不同,它接收的參數(shù)是一個(gè)Form的實(shí)例,并將這個(gè)實(shí)例注冊(cè)到NPSAppManaged管理的Form集合中。這里需要注意一下,registerForm只有兩個(gè)參數(shù),因?yàn)镕orm實(shí)例在方法前已經(jīng)實(shí)例化了,這里就不再接收和創(chuàng)建Form相關(guān)的參數(shù)。

通過(guò)以上三種方法創(chuàng)建的Form實(shí)例都可以通過(guò)self.parentApp來(lái)獲取到NPSAppManaged對(duì)象,如果想要移除Form,可以調(diào)用removeForm(id)方法。

運(yùn)行Application

通過(guò)前面的方法,我們已經(jīng)能夠創(chuàng)建并注冊(cè)自定義的Form對(duì)象到NPSAppManaged應(yīng)用中,接下來(lái)只要調(diào)用NPSAppManaged.run()方法就可以讓程序運(yùn)行起來(lái)了,如果你運(yùn)行之后發(fā)現(xiàn)出現(xiàn)了self._LAST_NEXT_ACTIVE_FORM = self._Forms[self.NEXT_ACTIVE_FORM] KeyError: 'MAIN',別急,那可能是我忘記告訴你設(shè)置程序的初始Form了。

NPSAppManaged.run()執(zhí)行時(shí),會(huì)默認(rèn)將Form id為‘MAIN’的Form作為初始Form顯示在界面內(nèi),如果沒(méi)有正確的設(shè)置‘MAIN’Form,就會(huì)出現(xiàn)類(lèi)似上面提到的異常情況。當(dāng)然,如果你不想使用‘MAIN’作為初始Form的id名稱(chēng),可以在調(diào)用run方法前修改NPSAppManaged.STARTING_FORM的值,來(lái)指定初始Form的id。

現(xiàn)在重新執(zhí)行run方法應(yīng)該就可以成功的運(yùn)行程序了,當(dāng)然現(xiàn)在我們的程序只有一個(gè)Form,太簡(jiǎn)陋,讀者可以試著多創(chuàng)建幾個(gè)Form,通過(guò)下列方法去按自己的方式控制程序顯示。

方法名 說(shuō)明
NPSAppManaged.setNextForm(formid) 設(shè)置下一個(gè)顯示的Form
NPSAppManaged.setNextFormPrevious() 將當(dāng)前Form的上一個(gè)Form設(shè)置為下一個(gè)顯示
NPSAppManaged.switchForm(formid) 切換到指定Form
NPSAppManaged.switchFormPrevious() 切換到指定Form的上一個(gè)Form

如果setNextFormswitchForm傳入?yún)?shù)為None,則退出程序

NPSAppManaged 生命周期函數(shù)

用于通過(guò)通過(guò)重寫(xiě)NPSAppManaged的部分方法來(lái)控制NPSAppManaged的生命周期

方法 說(shuō)明
NPSAppManaged.onInMainLoop() 在每個(gè)屏幕之間切換時(shí)調(diào)用(首屏不會(huì)調(diào)用)
NPSAppManaged.onStart() 初始化方法,可以在這里設(shè)置Form
NPSAppManaged.onCleanExit() 程序正常退出時(shí)調(diào)用此方法
Form.beforeEditing() 在Form初始前執(zhí)行
Form.afterEditing() 在退出Form時(shí)執(zhí)行

完整代碼

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 方向鍵上下超過(guò)可選數(shù)量時(shí), 會(huì)直接切換到上一個(gè)或下一個(gè)Widget
        # false 時(shí), 只能通過(guò)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__':
    # 設(shè)置自定義的初始Form id, 設(shè)置后, 'MAIN'將無(wú)法使用
    # MyApplication.STARTING_FORM = 'MyMain'
    TestApp = MyApplication().run()
    print("Application Exit")
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評(píng)論 19 139
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,187評(píng)論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,619評(píng)論 1 32
  • 過(guò)去的十月,幾多歡喜。 歡喜國(guó)慶的七天樂(lè),約上幾個(gè)新朋舊友,到處走走,歡歡熱鬧,說(shuō)說(shuō)笑笑。 歡喜井大的國(guó)際文化節(jié),...
    葫蘆娃大寶貝閱讀 556評(píng)論 0 0
  • 你有沒(méi)有經(jīng)常感覺(jué)腦容量不夠,不知書(shū)中作者在表達(dá)什么深?yuàn)W的觀點(diǎn)?你有沒(méi)人云亦云,風(fēng)吹兩邊倒,好像哪個(gè)評(píng)價(jià)說(shuō)的都對(duì)?這...
    肩上書(shū)閱讀 948評(píng)論 3 3

友情鏈接更多精彩內(nèi)容