使用 npyscreen 在表单之间传递值

Passing values between forms with npyscreen

我正在尝试在 python 中创建一个简单的 npyscreen curses 应用程序,它在一个屏幕上请求用户输入,然后在另一个屏幕上为用户验证它。

主要是为了了解如何在 npyscreen 中存储和检索值。我确信我遗漏了一些简单的东西,但我无法在文档中找到(或理解?)答案。

下面的示例代码无法正确传递值:

#!/usr/bin/env python3.5

import npyscreen as np

class EmployeeForm(np.Form):
    def afterEditing(self):
        self.parentApp.switchForm('CONFIRMFM')

    def create(self):
        self.myName = self.add(np.TitleText, name='Name')
        self.myDepartment = self.add(np.TitleSelectOne, scroll_exit=True, max_height=3, name='Department', values = ['Department 1', 'Department 2', 'Department 3'])
        self.myDate = self.add(np.TitleDateCombo, name='Date Employed')

class EmployeeConfirmForm(np.Form):
    def afterEditing(self):
        self.parentApp.setNextForm(None)

    def create(self):
        self.value = None
        self.wgName   = self.add(np.TitleText, name = "Name:",)
        self.wgDept = self.add(np.TitleText, name = "Dept:")
        self.wgEmp      = self.add(np.TitleText, name = "Employed:")

    def beforeEditing(self):
        if self.value:
            self.name = "Is this correct?"
            self.wgName.value   = self.myName.value
            self.wgDept.value = self.myDepartment.value
            self.wgEmp.value      = self.myDate.value

    def on_cancel(self):
        self.parentApp.switchFormPrevious()


class myApp(np.NPSAppManaged):
    def onStart(self):
        self.addForm('MAIN', EmployeeForm, name='Employee Entry')
        self.addForm('CONFIRMFM', EmployeeConfirmForm, name='Employee Confirmation')

if __name__ == '__main__':
    TestApp = myApp().run()

一种方法是在 switchForm 之前使用 getForm 来传递值。以下对我有用 python2 来传递名称。传递其他值应该类似。我自己也在学习这个,但如果您还有其他问题,请发表评论。

import npyscreen as np

class EmployeeForm(np.ActionForm):
    def create(self):
        self.myName = self.add(np.TitleText, name='Name')
        self.myDepartment = self.add(np.TitleSelectOne, scroll_exit=True, max_height=3, name='Department', values = ['Department 1', 'Department 2', 'Department 3'])
        self.myDate = self.add(np.TitleDateCombo, name='Date Employed')

    def afterEditing(self):
        self.parentApp.getForm('CONFIRMFM').wgName.value = self.myName.value
        self.parentApp.switchForm('CONFIRMFM')

class EmployeeConfirmForm(np.Form):
    def afterEditing(self):
        self.parentApp.setNextForm(None)

    def create(self):
        self.value = None
        self.wgName  = self.add(np.TitleFixedText, name = "Name:",)
        self.wgDept = self.add(np.TitleText, name = "Dept:")
        self.wgEmp      = self.add(np.TitleText, name = "Employed:")

    def on_cancel(self):
        self.parentApp.switchFormPrevious()

class myApp(np.NPSAppManaged):
    def onStart(self):
        self.addForm('MAIN', EmployeeForm, name='Employee Entry')
        self.addForm('CONFIRMFM', EmployeeConfirmForm, name='Employee Confirmation')

if __name__ == '__main__':
    TestApp = myApp().run()

我还没有找到直接在表单之间传递变量的直接方法。但是,您可以通过使用在表单之间具有全局范围的变量来解决这个问题。

NPSAppManaged 应用 class 完全封装运行,因此如果您尝试在 Python 文件的顶部声明全局变量,其中的表单将无法访问它们.相反,在 onStart 方法之前声明 NPSAppManaged app class 中的变量,如下所示。

class myApp(np.NPSAppManaged):

    # declare variables here that have global scope to all your forms
    myName, myDepartment, myDate = None, None, None

    def onStart(self):
        self.addForm('MAIN', EmployeeForm, name='Employee Entry')
        self.addForm('CONFIRMFM', EmployeeConfirmForm, name='Employee Confirmation')

if __name__ == '__main__':
    TestApp = myApp().run()

然后您可以使用 self.parentApp.[variable name] 访问这些变量,如下所示:

class EmployeeConfirmForm(np.Form):
    def afterEditing(self):
        self.parentApp.setNextForm(None)

    def create(self):
        self.add(np.FixedText, value = "Is this correct?")
        self.wgName = self.add(np.TitleText, name = "Name:", value = self.parentApp.myName)
        self.wgDept = self.add(np.TitleText, name = "Dept:", value = self.parentApp.myDepartment)
        self.wgEmp = self.add(np.TitleText, name = "Employed:", value = self.parentApp.myDate)

    def on_cancel(self):
        self.parentApp.switchFormPrevious()

注意:您不需要单独的 beforeEditing 方法,因为值将在 [=18] 期间直接加载到 EmployeeConfirmForm =] 来自应用程序的方法 class 全局变量。

给self.whatever赋值(包括addForm返回的值)。 所以如果你这样做

self.myAppValue = 2
self.mainForm = self.addForm('MAIN', MainForm, ...)
self.form2 = self.addForm('FORM2', Form2, ...)

您可以以任何形式使用这些

self.parentApp.myAppValue
self.parentApp.mainForm.main_form_widget.main_form_value

在 myApp() 中你可以做

self.mainForm.main_form_widget.main_form_value

我在开发过程中遇到了同样的问题,因为文档对于在表单之间传递值不是很详细。

我添加了一些修改,第一个是将确认表中的 Form 更改为 ActionForm 以访问 ok取消 按钮。其次,确认表上的值不应是可编辑的,因为这是确认。您可以按取消在上一个表格上进行编辑。最后一个是传递部门列表的第一个元素而不是值——它只是一个列表索引。希望对大家有所帮助。

#!/usr/bin/env python3.5

import npyscreen as np


class EmployeeForm(np.Form):

    def create(self):
        self.myName = self.add(np.TitleText, name='Name')
        self.myDepartment = self.add(np.TitleSelectOne, scroll_exit=True, max_height=3, name='Department', values = ['Department 1', 'Department 2', 'Department 3'])
        self.myDate = self.add(np.TitleDateCombo, name='Date Employed')

    def afterEditing(self):
        self.parentApp.switchForm('CONFIRMFM')
        self.parentApp.getForm('CONFIRMFM').wgName.value = self.myName.value
        self.parentApp.getForm('CONFIRMFM').wgDept.value = self.myDepartment.values[0]
        self.parentApp.getForm('CONFIRMFM').wgEmp.value = self.myDate.value


class EmployeeConfirmForm(np.ActionForm):

    def create(self):
        self.add(np.FixedText, value="Is this correct?", editable=False)
        self.wgName = self.add(np.TitleText, name = "Name:", editable=False)
        self.wgDept = self.add(np.TitleText, name = "Dept:", editable=False)
        self.wgEmp = self.add(np.TitleText, name = "Employed:", editable=False)

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

    def on_cancel(self):
        self.parentApp.switchFormPrevious()


class myApp(np.NPSAppManaged):

    def onStart(self):
        self.addForm('MAIN', EmployeeForm, name='Employee Entry')
        self.addForm('CONFIRMFM', EmployeeConfirmForm, name='Employee Confirmation')

if __name__ == '__main__':
    TestApp = myApp().run()