第 4 步 - 创建弹出窗口

在教程的这一步骤中,您将使用Kanzi Engine API 在弹出窗口中显示页面 (Page)主页面 (Page Host) 节点的内容。

创建 Settings 弹出窗口的结构

在本部分中,将结构添加到SettingsRoot 节点并设置,使其显示在HomeMediaCar 应用程序顶部。

如果要始终将页面 (Page)主页面 (Page Host) 节点内容显示在应用程序弹出窗口顶部,在其他所有内容之上,则必须将该页面 (Page)主页面 (Page Host) 节点作为场景图中的最后一个节点,以便Kanzi 总是最先渲染它。

要创建 Settings 弹出窗口的结构:

  1. 页面 (Pages) 中,在主页面 (Page Host) 节点 SettingsRoot 的右上角点击 启用保持活动状态 (Keep Active) 属性。
    您启用保持活动状态 (Keep Active) 属性时,Kanzi 激活该页面 (Page)主页面 (Page Host) 节点,无论其父页面 (Page)主页面 (Page Host) 节点是否活动。页面 (Page)主页面 (Page Host) 节点活动时,其内容显示,您可与其交互。由于您使用 SettingsRoot 节点保存的内容在应用程序用户界面中会以所有其他应用程序内容顶部的弹出窗口形式显示,所以 SettingsRoot 节点本身为空并显示其子页面 (Page) 节点。
  2. 页面 (Pages) 中,在主页面 (Page Host) 节点 SettingsRoot 底部点击 ,在该节点下创建子页面 (Page) 节点,并命名为 Settings
  3. 右键点击在上一步中创建的 Settings 节点并选择转换为主页面 (Convert to Page Host)
    页面 (Page) 节点 Settings 转换为主页面 (Page Host) 节点,在导航至父节点时可关闭 Settings 弹出窗口。
  4. 页面 (Pages) 中,在 Settings 节点底部点击 三下,在 Settings 节点下创建三个子页面 (Page) 节点,并将其命名为 AirConditionSeatAdjustmentRearSeats
  5. 资产 (Assets) 拖到页面 (Pages) 窗口:
  6. 工程 (Project) 中选择Settings 主页面 (Page Host) 节点,并在属性 (Properties) 中将默认子页 (Default Subpage) 属性设为 AirCondition 节点。
  7. Settings 弹出窗口打开时调暗选定页面 (Page) 节点:
    1. 工程 (Project) 中选择 AirCondition 节点,在属性 (Properties) 中添加背景笔刷 (Background Brush) 属性,选择 + 颜色笔刷 (+ Color Brush),点击属性名称旁的 ,并将阿尔法通道 (Alpha) 设为 127,使颜色笔刷 (Color Brush) 变成透明灰。
    2. 工程 (Project) 中选择 SeatAdjustmentRearSeats 节点,在属性 (Properties) 中添加背景笔刷 (Background Brush) 属性,并将其设为您在上一步创建的颜色笔刷 (Color Brush)

使用Settings 弹出窗口创建导航

在本节中,在 Settings 弹出窗口中为页面 (Page) 节点 AirConditionSeatAdjustmentRearSeats 创建导航。通过导航,用户可以在主页面 (Page Host) 节点 Settings 中的页面 (Page) 节点之间导航并关闭弹出窗口。

要使用Settings 弹出窗口创建导航:

  1. 工程 (Project)按下 Alt 并右键点击Settings 节点,选择 2D 网格布局 (Grid layout 2D) 并将其命名为 SettingsNavigation
  2. 预览 (Preview) 中使用节点工具 (Node tool) 定位并重设SettingsNavigation 节点大小,使其覆盖图像 (Image) 节点 Settings_AC 中的关闭、上一步和下一步按钮。
  3. 工程 (Project) 中选择SettingsNavigation 节点,并在属性 (Properties) 中:
  4. 创建导航按钮:
    1. 工程 (Project)SettingsNavigation 节点中,创建一个 2D 按钮 (Button 2D) 节点并命名为“Close”。
    2. 工程 (Project) 中选择Close 节点,在属性 (Properties) 右下角点击 打开添加属性 (Add Properties) 窗口。在添加属性 (Add Properties) 窗口的左侧栏中双击列 (Column)行 (Row) 属性,将其添加到您选定的节点。
      在打开的添加属性 (Add Properties) 窗口的左侧栏中,您可以查看能将哪些属性添加到在工程 (Project) 窗口中选择的节点。
      建议

      要快速找到属性,在 添加属性 (Add Properties) 窗口的搜索框中键入属性名称的几个字母。

    3. 工程 (Project) 中选择Close 节点并在属性 (Properties) 中添加和设置:
      • 列 (Column) 为 1
      • 行 (Row) 为 0
      • 布局宽度 (Layout Width) 为 100
      • 布局高度 (Layout Height) 为 100
      • 水平对齐 (Horizontal Alignment)右对齐 (Right)
      通过这种方式,您可以放置第一行第二列中的Close 节点、设置其大小并将其对齐到右侧。
    4. 工程 (Project)SettingsNavigation 节点中,创建一个 2D 按钮 (Button 2D) 节点,命名为“Previous”,并在 属性 (Properties) 添加并进行以下设置:
      • 列 (Column) 为 0
      • 行 (Row) 为 1
      • 布局高度 (Layout Height) 为 170
    5. 工程 (Project) 右键点击 Previous 节点,选择 重复 (Duplicate),按下 F2 键,将新节点重命名为 Next,并在 属性 (Properties) 中进行以下设置:
      • 列 (Column) 为 1
      • 水平对齐 (Horizontal Alignment)右对齐 (Right)

  5. Kanzi Engine API 中为您需要访问的节点创建别名:
    1. 工程 (Project)按下 Alt 并右键点击 Settings 节点并选择别名 (Alias)
      使用别名 (Alias) 实现对 Kanzi 节点的一致访问。您可以使用别名在 Kanzi StudioKanzi Engine API 或脚本中访问节点。
    2. 重复上一步为以下节点创建别名:
      • SettingsButton 节点
      • Close 节点
      • Previous 节点
      • Next 节点

      您可以在字典 (Dictionaries) 窗口看到您的工程中的别名。

    3. 字典 (Dictionaries) 中,从 Settings 节点的资源字典中拖动 Settings 别名到屏幕 (Screen) 节点的资源字典。
      这样即可从屏幕 (Screen) 节点访问别名。
  6. 选择文件 (File) > 导出 (Export) > 导出 KZB (Export KZB)
    Kanzi StudioKanzi Studio 工程创建 kzb 文件和配置文件。Kanzi Studio 将导出的文件存储在 <ProjectName>/Application/bin 目录或您在 工程 (Project) > 属性 (Properties)二进制导出目录 (Binary Export Directory) 属性中指定的位置。Kzb 文件包含 Kanzi Studio 工程中的所有节点和资源,您在本地化表中标记为本地化包的资源除外。
    当您从 Visual Studio 中运行您的 Kanzi 应用程序时,您的应用程序就会加载 kzb 文件和配置文件。

Kanzi Engine API 在弹出窗口中显示 Settings 节点

在本节中,您将添加代码到应用程序中,以在弹出窗口中显示 Settings 节点的内容,并将用户导航起点和终点的页面 (Page) 节点名称打印至 Kanzi 调试控制台。

要用 Kanzi Engine API 在弹出窗口中显示 Settings 节点:

  1. 在 Visual Studio 中,为您的应用程序打开位于 Application/configs/platforms/win32 的 Visual Studio 解决方案。

    如果您在 Visual Studio 2017 中打开教程解决方案,遇到提示您重新定位工程到最新的 Microsoft 工具集时,请点击取消 (Cancel)。

  2. pages.cpp 文件中,在 onConfigure 函数中设置应用程序窗口的尺寸:
    class Pages : public ExampleApplication
    {
    public: 
    
        virtual void onConfigure(ApplicationProperties& configuration) KZ_OVERRIDE
        {
            //设置应用程序窗口的大小,使其匹配屏幕 (Screen) 节点的大小。
            configuration.defaultWindowProperties.width = 1200;
            configuration.defaultWindowProperties.height = 720;
    
            ...
        }
  3. Pages 类的 pages.cpp 私有部分,为 Settings 节点和 SettingsButton 节点添加指针:
    private: 
    
        Node2DSharedPtr m_settingsButton;
        PageHostSharedPtr m_settingsPageHost;
  4. onProjectLoaded 函数中,获取需要在 Settings 弹出窗口中导航的节点:
         virtual void onProjectLoaded() KZ_OVERRIDE
        {
            //获取屏幕 (Screen) 节点。
            ScreenSharedPtr screen = getScreen();
    
            //获取导航至 Settings 节点的按钮。
            m_settingsButton = screen->lookupNode<Node2D>("#SettingsButton");
    
            //使用 Settings 节点的别名获取该节点。
            m_settingsPageHost = screen->lookupNode<PageHost>("#Settings");
        }
    
  5. Pages 类的私有部分注册SettingsButton 节点的消息处理程序:
    private: 
    
        //定义来自 SettingsButton 节点的 ToggledOn 消息处理程序。
        //用户点击 SettingsButton 时,导航至 Settings 页面。
        void onSettingsButtonToggledOn(ButtonConcept::ToggledOnMessageArguments& /*message*/)
        {
            //发送 Navigate 消息至主页面 (Page Host) 节点 Settings 以显示该页面。
            PageHost::NavigateMessageArguments args;
            m_settingsPageHost->dispatchMessage(PageHost::NavigateMessage, args);
        }
    
        //定义来自 SettingsButton 节点的 ToggledOff 消息处理程序。
        //用户点击 SettingsButton 时,关闭 Settings 页面。
        void onSettingsButtonToggledOff(ButtonConcept::ToggledOffMessageArguments& /*message*/)
        {
            //发送 NavigateParent 消息至主页面 (Page Host) 节点 Settings主页面 (Page Host) 以关闭 Settings 页面。
            PageHost::NavigateParentMessageArguments args;
            m_settingsPageHost->dispatchMessage(PageHost::NavigateParentMessage, args);
        }
  6. SettingsButton 节点的消息处理程序后的私有部分,为 NextPreviousClose 按钮添加消息处理程序:
    private: 
        ...
    
        //定义来自 Next 按钮的 Button.Pressed 消息处理程序。
        //用户点击 Next 按钮时,导航至主页面 (Page Host) 节点 Settings 的下一个子页面。
        void onNextButtonClicked(ButtonConcept::PressedMessageArguments&)
        {
            //发送 NavigateNext 消息至主页面 (Page Host) 节点Settings 以导航至主页面 (Page Host) 的下一个子页面。
            PageHost::NavigateNextMessageArguments args;
            m_settingsPageHost->dispatchMessage(PageHost::NavigateNextMessage, args);
        }
    
        //定义来自 Previous 按钮的 Button.Pressed 消息处理程序。
        //用户点击 Previous 按钮时,导航至主页面 (Page Host) 节点 Settings 的上一个子页面。
        void onPreviousButtonClicked(ButtonConcept::PressedMessageArguments&)
        {
            //发送 NavigatePrevious 消息至主页面 (Page Host) 节点 Settings,以导航至主页面 (Page Host) 的上一个子页面。
            PageHost::NavigatePreviousMessageArguments args;
            m_settingsPageHost->dispatchMessage(PageHost::NavigatePreviousMessage, args);
        }
    
        //定义来自 Close 按钮的 Button.Pressed 消息处理程序。
        //用户点击 Close 按钮时,关闭 Settings 节点并导航至
        //活动的页面 (Page) 节点。
        void onCloseButtonClicked(ButtonConcept::PressedMessageArguments&)
        {
            //关闭 SettingsButton。当 SettingsButton 关闭时,它发送 ToggledOff 消息,
            //由 Application::onSettingsButtonToggledOff() 函数处理。此
            //处理程序函数关闭 NavigateParent 消息以关闭 Settings 页面。
            m_settingsButton->setProperty(ButtonConcept::ToggleStateProperty, 0);
        }
  7. onProjectLoaded 函数中注册您在上一步中创建的消息处理程序:
        virtual void onProjectLoaded() KZ_OVERRIDE
        {
            ...
    
            //定义来自 SettingsButton 节点的 ToggledOnMessage 和 ToggledOffMessage 消息处理程序。
            m_settingsButton->addMessageHandler(ButtonConcept::ToggledOnMessage, bind(&Pages::onSettingsButtonToggledOn, this, placeholders::_1));
            m_settingsButton->addMessageHandler(ButtonConcept::ToggledOffMessage, bind(&Pages::onSettingsButtonToggledOff, this, placeholders::_1));
    
            //注册来自主页面 (Page Host) 节点 Settings 中导航按钮的 Button.Pressed 消息的消息处理程序。
            //订阅 Next 节点的 Button.Pressed 消息。当用户按下该按钮时,2D 按钮 (Button 2D)节点 Next 生成此消息。
            Button2DSharedPtr gotoNextPageButton = m_settingsPageHost->lookupNode<Button2D>("#Next");
            gotoNextPageButton->addMessageHandler(ButtonConcept::PressedMessage, bind(&Pages::onNextButtonClicked, this, placeholders::_1));
    
            //订阅 Previous 节点的 Button.Pressed 消息。当用户按下该按钮时,2D 按钮 (Button 2D)节点 Previous 生成此消息。
            Button2DSharedPtr gotoPreviousPageButton = m_settingsPageHost->lookupNode<Button2D>("#Previous");
            gotoPreviousPageButton->addMessageHandler(ButtonConcept::PressedMessage, bind(&Pages::onPreviousButtonClicked, this, placeholders::_1));
    
            //定义 Close 节点的 Button.Pressed 消息。当用户按下该按钮时,2D 按钮 (Button 2D)节点 Close 生成此消息。
            Button2DSharedPtr closeButton = m_settingsPageHost->lookupNode<Button2D>("#Close");
            closeButton->addMessageHandler(ButtonConcept::PressedMessage, bind(&Pages::onCloseButtonClicked, this, placeholders::_1));
        }
  8. onCloseButtonClicked 函数后的私有部分添加处理程序,将用户导航的页面 (Page)主页面 (Page Host) 节点名称打印至 Kanzi 调试控制台:
    private: 
        ...
    
        //定义来自各 主页面 (Page Host) 节点的 Page.NavigationStarted 消息处理程序。
        //页面导航开始时,将导航开始的主页面 (Page Host) 节点名称
        //打印至 Kanzi 调试控制台。
        void onPageNavigationStarted(PageHost::NavigationStartedMessageArguments& message)
        {
            kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Page navigation started: {}", message.getSource()->getName()));
        }
    
        //定义来自各主页面 (Page Host) 节点的 Page.NavigationFinished 消息处理程序。
        //页面导航结束时,将导航结束的主页面 (Page Host) 节点名称
        //打印至 Kanzi 调试控制台。
        void onPageNavigationFinished(PageHost::NavigationFinishedMessageArguments& message)
        {
            kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Page navigation finished: {}", message.getSource()->getName()));
        }
    
        //定义来自各页面 (Page) 节点的 Page.Activated 消息处理程序。
        //当页面 (Page) 节点活动时,将页面 (Page) 节点的名称
        //打印至 Kanzi 调试控制台。
        void onPageActivated(Page::ActivatedMessageArguments& message)
        {
            kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Page activated: {}", message.getSource()->getName()));
        }
    
        //定义来自各页面 (Page) 节点的 Page.Deactivated 消息处理程序。
        //当页面 (Page) 节点停用时,将页面 (Page) 节点的名称
        //打印至 Kanzi 调试控制台。
        void onPageDeactivated(Page::DeactivatedMessageArguments& message)
        {
            kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Page deactivated: {}", message.getSource()->getName()));
        }
  9. onProjectLoaded 函数中添加用于跟踪页面导航的消息过滤器:
        virtual void onProjectLoaded() KZ_OVERRIDE
        {
            ...
    
            //添加消息过滤器,以侦听页面 (Page)主页面 (Page Host) 节点之间的导航。
            //这些消息过滤器允许 Kanzi 跟踪应用程序中的导航,
            //有助于调试。
            screen->addMessageFilter(PageHost::NavigationStartedMessage, bind(&Pages::onPageNavigationStarted, this, placeholders::_1));
            screen->addMessageFilter(PageHost::NavigationFinishedMessage, bind(&Pages::onPageNavigationFinished, this, placeholders::_1));
    
            screen->addMessageFilter(Page::ActivatedMessage, bind(&Pages::onPageActivated, this, placeholders::_1));
            screen->addMessageFilter(Page::DeactivatedMessage, bind(&Pages::onPageDeactivated, this, placeholders::_1));
        }
  10. 在 Visual Studio 中,为您的 Visual Studio 版本选择一个解决方案配置并运行应用程序。
    例如,如果您仍在开发应用程序,选择GL_vs2015_Debug 配置。要创建 Kanzi 应用程序的产品版本,选择一个可用的发布配置。

    要在 Kanzi 调试控制台中查看页面导航消息,选择 GL_vs2015_Debug 配置。

运行该应用程序时,可以导航至 Settings 弹出页面,并浏览该页面的子页面。每次在应用程序中导航至页面时,Kanzi 打印导航起始和结束的主页面 (Page Host) 节点名称,以及页面 (Page) 或激活和停用的主页面 (Page Host) 节点。



< 上一步

接下来该做什么?

在本教程中,您学习了如何使用页面 (Page)主页面 (Page Host) 节点通过页面 (Pages) 工具创建应用程序流和结构。要继续学习 Kanzi 您可以:

另请参阅

要详细了解有关页面 (Page)主页面 (Page Host) 节点的信息,请参阅使用页面 (Page) 和主页面 (Page Host) 节点

要了解有关使用状态机的更多信息,请参阅使用状态机

要详细了解有关使用触发器和动作的信息,请参阅触发器