5.14. 使用 NormalTUISpoke 来定义文本接口 Spoke


重新定义简单 TUI Spoke 示例演示了一种实现 TUI spoke 的方法,其中它的方法处理打印和处理可用的和提供的数据。但是,使用 pyanaconda.ui.tui.spokes 软件包中的 NormalTUISpoke 类可以以不同的方式完成此操作。通过继承此类,您只需指定应在其中设置的字段和属性,就可实现典型的 TUI spoke 。以下示例演示了这一点:

先决条件

流程

  • 根据以下示例,创建带有所有必要定义的模块,来对 Add-on 文本用户界面(TUI)添加支持。

例 5.12. 使用 NormalTUISpoke 来定义文本接口 Spoke

class HelloWorldEditSpoke(NormalTUISpoke):
    """Example class demonstrating usage of editing in TUI"""
    category = HelloWorldCategory

    def init(self, data, storage, payload):
        """
        :see: simpleline.render.screen.UIScreen
        :param data: data object passed to every spoke to load/store data
                     from/to it
        :type data: pykickstart.base.BaseHandler
        :param storage: object storing storage-related information
                        (disks, partitioning, boot loader, etc.)
        :type storage: blivet.Blivet
        :param payload: object storing packaging-related information
        :type payload: pyanaconda.packaging.Payload
        """
        super().init(self, *args, **Kwargs)

        self.title = N_("Hello World Edit")
        self._container = None

        # values for user to set
        self._checked = False
        self._unconditional_input = ""
        self._conditional_input = ""

    def refresh(self, args=None):
        """
        The refresh method that is called every time the spoke is displayed.
        It should update the UI elements according to the contents of self.data.
        :see: pyanaconda.ui.common.UIObject.refresh
        :see: simpleline.render.screen.UIScreen.refresh
        :param args: optional argument that may be used when the screen is
                     scheduled
        :type args: anything
        """
        super().refresh(args)
        self._container = ListColumnContainer(columns=1)

        # add ListColumnContainer to window (main window container)
        # this will automatically add numbering and will call callbacks when required
        self.window.add(self._container)

        self._container.add(CheckboxWidget(title="Simple checkbox", completed=self._checked),
                            callback=self._checkbox_called)
        self._container.add(EntryWidget(title="Unconditional text input",
                                        value=self._unconditional_input),
                            callback=self._get_unconditional_input)

        # show conditional input only if the checkbox is checked
        if self._checked:
            self._container.add(EntryWidget(title="Conditional password input",
                                            value="Password set" if self._conditional_input
                                            else ""),
                                callback=self._get_conditional_input)

        self.window.add_with_separator(self._container)
    def _checkbox_called(self, data):  # pylint: disable=unused-argument
        """Callback when user wants to switch checkbox.

        :param data: can be passed when adding callback in container (not used here)
        :type data: anything
        """
        self._checked = not self._checked

    def _get_unconditional_input(self, data):  # pylint: disable=unused-argument
        """Callback when the user wants to set unconditional input.

        :param data: can be passed when adding callback in container (not used here)
        :type data: anything
        """
        dialog = Dialog(
            "Unconditional input",
            conditions=[self._check_user_input]
        )
        self._unconditional_input = dialog.run()

    def _get_conditional_input(self, data):  # pylint: disable=unused-argument
        """Callback when the user wants to set conditional input.

        :param data: can be passed when adding callback in container (not used here)
        :type data: anything
        """
        dialog = PasswordDialog(
            "Unconditional password input",
            policy_name=PASSWORD_POLICY_ROOT
        )
        self._conditional_input = dialog.run()

    def _check_user_input(self, user_input, report_func):
        """Check if the user has written a valid value.

        :param user_input: user input for validation
        :type user_input: str

        :param report_func: function for reporting errors on user input
        :type report_func: func with one param
        """
        if re.match(r'^\w+$', user_input):
            return True
        else:
            report_func("You must set at least one word")
            return False

    def input(self, args, key):
        """
        The input method that is called by the main loop on user's input.

        :param args: optional argument that may be used when the screen is
                     scheduled
        :type args: anything
        :param key: user's input
        :type key: unicode
        :return: if the input should not be handled here, return it, otherwise
                 return InputState.PROCESSED or InputState.DISCARDED if the input was
                 processed successfully or not respectively
        :rtype: enum InputState
        """
        if self._container.process_user_input(key):
            return InputState.PROCESSED_AND_REDRAW
        else:
            return super().input(args, key)


    @property
    def completed(self):
        # completed if user entered something non-empty to the Conditioned input
        return bool(self._conditional_input)

    @property
    def status(self):
        return "Hidden input %s" % ("entered" if self._conditional_input
                                    else "not entered")

    def apply(self):
        # nothing needed here, values are set in the self.args tree
        pass
Copy to Clipboard Toggle word wrap
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat