程序結(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 |
如果
setNextForm或switchForm傳入?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")