当前位置: 首页 > article >正文

Chromium GN 目标指南 - view_examples 自定义Button示例 (六)

1. 引言

在上一篇文章中,我们介绍了 views_examples 这一重要的示例程序,它展示了 Chromium Views 框架中各种控件的使用方法。在本篇文章中,我们将更进一步,尝试在 views_examples 中添加自定义的 Button 示例,以学习如何创建和使用自定义控件,并将其集成到现有的 GN 目标中。

2. 创建自定义 Button 示例

为了添加自定义的 Button 示例,我们需要创建新的头文件和源文件,并在其中定义我们的自定义 Button 类和相关的示例代码。

2.1 创建头文件

首先,我们在 ui/views/examples/ 目录下创建一个名为 my_custom_button_example.h 的头文件,并在其中添加以下代码:

#ifndef UI_VIEWS_EXAMPLES_MY_CUSTOM_BUTTON_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_MY_CUSTOM_BUTTON_EXAMPLE_H_

#include "ui/views/controls/button/button.h"
#include "ui/views/controls/label.h"
#include "ui/views/examples/example_base.h"

namespace views::examples {

class MyCustomButtonExample : public ExampleBase {
 public:
  MyCustomButtonExample();
  MyCustomButtonExample(const MyCustomButtonExample&) = delete;
  MyCustomButtonExample& operator=(const MyCustomButtonExample&) = delete;
  ~MyCustomButtonExample() override = default;

  // ExampleBase:
  void CreateExampleView(View* container) override;

 private:
  void OnButtonClicked();
  void OnIconButtonClicked();
  void OnStyledButtonClicked();

  raw_ptr<views::Label> status_label_ = nullptr;
};

}  // namespace views::examples

#endif  // UI_VIEWS_EXAMPLES_MY_CUSTOM_BUTTON_EXAMPLE_H_

这段代码定义了一个名为 MyCustomButtonExample 的类,它继承自 ExampleBaseExampleBaseviews_examples 中所有示例的基类,提供了一些通用的功能。

MyCustomButtonExample 类中,我们声明了三个私有成员函数:OnButtonClickedOnIconButtonClickedOnStyledButtonClicked,分别用于处理三种不同按钮的点击事件。我们还声明了一个 raw_ptr<views::Label> 类型的成员变量 status_label_,用于显示按钮点击后的状态信息。

2.2 创建源文件

接下来,我们在 ui/views/examples/ 目录下创建一个名为 my_custom_button_example.cc 的源文件,并在其中添加以下代码:

#include "ui/views/examples/my_custom_button_example.h"

#include "base/functional/bind.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/vector_icons.h"
#include "base/logging.h"

namespace views::examples {

MyCustomButtonExample::MyCustomButtonExample() : ExampleBase("custom button example") {}

void MyCustomButtonExample::CreateExampleView(View* container) {
  // 使用垂直布局
  auto* layout = new views::BoxLayout(
      views::BoxLayout::Orientation::kVertical, 
      gfx::Insets(10), // 边距
      10); // 按钮间距
  container->SetLayoutManager(std::unique_ptr<views::BoxLayout>(layout));

  // 1. 基础按钮
  auto* basic_button = new views::MdTextButton(
      base::BindRepeating(&MyCustomButtonExample::OnButtonClicked,
                         base::Unretained(this)),
      u"basic button");
  container->AddChildView(basic_button);

  // 2. 带图标的按钮
  auto* icon_button = new views::MdTextButton(
      base::BindRepeating(&MyCustomButtonExample::OnIconButtonClicked,
                         base::Unretained(this)),
      u"icon button");
  icon_button->SetImageModel(
      views::Button::STATE_NORMAL,
      ui::ImageModel::FromVectorIcon(views::kInfoIcon));
  container->AddChildView(icon_button);

  // 3. 自定义样式按钮
  auto* styled_button = new views::MdTextButton(
      base::BindRepeating(&MyCustomButtonExample::OnStyledButtonClicked,
                         base::Unretained(this)),
      u"styled button");
  styled_button->SetStyle(ui::ButtonStyle::kTonal);
  container->AddChildView(styled_button);

  // 4. 状态标签
  status_label_ = new views::Label(u"click button to see effect");
  container->AddChildView(status_label_);
}

void MyCustomButtonExample::OnButtonClicked() {
  status_label_->SetText(u"basic button clicked");
  LOG(INFO) << "Basic button clicked";
}

void MyCustomButtonExample::OnIconButtonClicked() {
  status_label_->SetText(u"icon button clicked");
  LOG(INFO) << "Icon button clicked";
}

void MyCustomButtonExample::OnStyledButtonClicked() {
  status_label_->SetText(u"styled button clicked");
  LOG(INFO) << "Styled button clicked";
}

}  // namespace views::examples

这段代码实现了 MyCustomButtonExample 类的构造函数和 CreateExampleViewOnButtonClickedOnIconButtonClickedOnStyledButtonClicked 方法。

  • MyCustomButtonExample::MyCustomButtonExample(): 构造函数,调用了父类 ExampleBase 的构造函数,并设置了示例的名称为 "custom button example"。
  • MyCustomButtonExample::CreateExampleView(View* container): 这个方法负责创建并添加按钮到 container 中。
    • 首先,它创建了一个垂直布局管理器 BoxLayout,并将其设置给 container
    • 然后,它创建了三种不同类型的按钮:
      • basic_button: 一个普通的文本按钮,点击后会调用 OnButtonClicked 方法。
      • icon_button: 一个带图标的文本按钮,点击后会调用 OnIconButtonClicked 方法。这里使用了 views::kInfoIcon 作为按钮图标。
      • styled_button: 一个自定义样式的文本按钮,点击后会调用 OnStyledButtonClicked 方法。这里使用了 ui::ButtonStyle::kTonal 样式。
    • 最后,它创建了一个 Label 控件 status_label_,用于显示按钮点击后的状态信息。
  • MyCustomButtonExample::OnButtonClicked(): 当 basic_button 被点击时,这个方法会被调用。它会将 status_label_ 的文本设置为 "basic button clicked",并在日志中输出 "Basic button clicked"。
  • MyCustomButtonExample::OnIconButtonClicked(): 当 icon_button 被点击时,这个方法会被调用。它会将 status_label_ 的文本设置为 "icon button clicked",并在日志中输出 "Icon button clicked"。
  • MyCustomButtonExample::OnStyledButtonClicked(): 当 styled_button 被点击时,这个方法会被调用。它会将 status_label_ 的文本设置为 "styled button clicked",并在日志中输出 "Styled button clicked"。

3. 修改 BUILD.gn 文件

为了将我们的自定义 Button 示例添加到构建系统中,我们需要修改 ui/views/examples/BUILD.gn 文件,将我们新创建的源文件添加到 examples 目标的 sources 属性中。

打开 ui/views/examples/BUILD.gn 文件,找到 views_examples_lib 部分,并在 sources 列表中添加以下两行:

"my_custom_button_example.cc",
"my_custom_button_example.h",

4. 注册示例

最后,我们需要在 ui/views/examples/create_examples.cc 文件中注册我们的自定义示例,这样 views_examples 程序才能找到并显示它。

打开 ui/views/examples/create_examples.cc 文件,找到 CreateExamples 函数,并在 examples 向量中添加以下代码:

#include "ui/views/examples/my_custom_button_example.h"

// exists code

examples.push_back(std::make_unique<MyCustomButtonExample>());

添加完后代码如下

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/examples/create_examples.h"

#include <memory>
#include <utility>

#include "build/build_config.h"
#include "ui/views/examples/actions_example.h"
#include "ui/views/examples/animated_image_view_example.h"
#include "ui/views/examples/animation_example.h"
#include "ui/views/examples/ax_example.h"
#include "ui/views/examples/badge_example.h"
#include "ui/views/examples/box_layout_example.h"
#include "ui/views/examples/bubble_example.h"
#include "ui/views/examples/button_example.h"
#include "ui/views/examples/button_sticker_sheet.h"
#include "ui/views/examples/checkbox_example.h"
#include "ui/views/examples/colored_dialog_example.h"
#include "ui/views/examples/colors_example.h"
#include "ui/views/examples/combobox_example.h"
#include "ui/views/examples/designer_example.h"
#include "ui/views/examples/dialog_example.h"
#include "ui/views/examples/fade_animation.h"
#include "ui/views/examples/flex_layout_example.h"
#include "ui/views/examples/ink_drop_example.h"
#include "ui/views/examples/label_example.h"
#include "ui/views/examples/link_example.h"
#include "ui/views/examples/login_bubble_dialog_example.h"
#include "ui/views/examples/menu_example.h"
#include "ui/views/examples/message_box_example.h"
#include "ui/views/examples/multiline_example.h"
#include "ui/views/examples/notification_example.h"
#include "ui/views/examples/progress_bar_example.h"
#include "ui/views/examples/radio_button_example.h"
#include "ui/views/examples/scroll_view_example.h"
#include "ui/views/examples/slider_example.h"
#include "ui/views/examples/square_ink_drop_example.h"
#include "ui/views/examples/tabbed_pane_example.h"
#include "ui/views/examples/table_example.h"
#include "ui/views/examples/text_example.h"
#include "ui/views/examples/textarea_example.h"
#include "ui/views/examples/textfield_example.h"
#include "ui/views/examples/throbber_example.h"
#include "ui/views/examples/toggle_button_example.h"
#include "ui/views/examples/tree_view_example.h"
#include "ui/views/examples/typography_example.h"
#include "ui/views/examples/vector_example.h"
#include "ui/views/examples/widget_example.h"
#include "ui/views/examples/my_custom_button_example.h"

#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_FUCHSIA)
#include "ui/views/examples/color_chooser_example.h"
#endif

namespace views::examples {

// Creates the default set of examples.
ExampleVector CreateExamples(ExampleVector extra_examples) {
  ExampleVector examples = std::move(extra_examples);
  examples.push_back(std::make_unique<ActionsExample>());
  examples.push_back(std::make_unique<AnimatedImageViewExample>());
  examples.push_back(std::make_unique<AnimationExample>());
  examples.push_back(std::make_unique<AxExample>());
  examples.push_back(std::make_unique<BadgeExample>());
  examples.push_back(std::make_unique<BoxLayoutExample>());
  examples.push_back(std::make_unique<BubbleExample>());
  examples.push_back(std::make_unique<ButtonExample>());
  examples.push_back(std::make_unique<ButtonStickerSheet>());
  examples.push_back(std::make_unique<CheckboxExample>());
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_FUCHSIA)
  examples.push_back(std::make_unique<ColorChooserExample>());
#endif
  examples.push_back(std::make_unique<ColoredDialogExample>());
  examples.push_back(std::make_unique<ColorsExample>());
  examples.push_back(std::make_unique<ComboboxExample>());
  examples.push_back(std::make_unique<DesignerExample>());
  examples.push_back(std::make_unique<DialogExample>());
  examples.push_back(std::make_unique<FadeAnimationExample>());
  examples.push_back(std::make_unique<FlexLayoutExample>());
  examples.push_back(std::make_unique<InkDropExample>());
  examples.push_back(std::make_unique<LabelExample>());
  examples.push_back(std::make_unique<LinkExample>());
  examples.push_back(std::make_unique<LoginBubbleDialogExample>());
  examples.push_back(std::make_unique<MenuExample>());
  examples.push_back(std::make_unique<MessageBoxExample>());
  examples.push_back(std::make_unique<MultilineExample>());
  examples.push_back(std::make_unique<NotificationExample>());
  examples.push_back(std::make_unique<ProgressBarExample>());
  examples.push_back(std::make_unique<RadioButtonExample>());
  examples.push_back(std::make_unique<ScrollViewExample>());
  examples.push_back(std::make_unique<SliderExample>());
  examples.push_back(std::make_unique<SquareInkDropExample>());
  examples.push_back(std::make_unique<TabbedPaneExample>());
  examples.push_back(std::make_unique<TableExample>());
  examples.push_back(std::make_unique<TextExample>());
  examples.push_back(std::make_unique<TextareaExample>());
  examples.push_back(std::make_unique<TextfieldExample>());
  examples.push_back(std::make_unique<ToggleButtonExample>());
  examples.push_back(std::make_unique<ThrobberExample>());
  examples.push_back(std::make_unique<TreeViewExample>());
  examples.push_back(std::make_unique<TypographyExample>());
  examples.push_back(std::make_unique<VectorExample>());
  examples.push_back(std::make_unique<WidgetExample>());
  examples.push_back(std::make_unique<MyCustomButtonExample>());
  return examples;
}

}  // namespace views::examples

5. 重新编译并运行

完成以上步骤后,我们需要重新编译 views_examples 目标。在 Chromium 源码的 src 目录下执行以下命令:

autoninja -C out/Default views_examples

这里假设您的构建目录为 out/Default,如果不是请对应修改

编译完成后,运行 views_examples

./out/Default/views_examples

如果一切顺利,你将在 "Views Examples" 窗口中看到一个新的标签页 "custom button example",点击该标签页,你将看到我们自定义的三种不同类型的按钮,以及一个用于显示状态信息的 Label。点击不同的按钮,Label 的文本会相应地改变,同时终端中也会输出相应的日志信息。

6. 结语

在本篇文章中,我们学习了如何在 views_examples 中添加自定义的 Button 示例,包括创建头文件和源文件、修改 BUILD.gn 文件、注册示例以及重新编译和运行。通过这个过程,我们学习了如何创建和使用自定义控件,并将其集成到现有的 GN 目标中。

希望这篇文章能够帮助你更好地理解 Chromium 的 Views 框架和 GN 构建系统,为你在 Chromium 平台上的 UI 开发提供帮助。在接下来的文章中,我们将继续探索 Chromium 和 GN 的更多高级用法。


http://www.kler.cn/a/451682.html

相关文章:

  • linux中 mysql备份
  • LeetCode:257. 二叉树的所有路径
  • Kafka可视化工具 Offset Explorer (以前叫Kafka Tool)
  • (带源码)宠物主题商场系统 计算机项目 P10083
  • vue3 Proxy替换vue2 defineProperty的原因
  • 低空经济的地理信息支撑:构建安全、高效的飞行管理体系
  • 【es6复习笔记】let 和 const 命令(1)
  • Django models中的增删改查与MySQL SQL的对应关系
  • leetcode hot100 环形链表2
  • 深度学习环境安装
  • 内网穿透玩法之京东云亚瑟路由器刷神卓互联教程
  • 树莓集团:以产教融合助力人才培养
  • yii2 手动添加 phpoffice\phpexcel
  • 开放世界目标检测 Grounding DINO
  • 机器人C++开源库The Robotics Library (RL)使用手册(一)
  • CentOS7下的vsftpd服务器和客户端
  • 基于推理的目标检测 DetGPT
  • Python选择题训练工具:高效学习、答题回顾与音频朗读一站式体验
  • 如何将excel表格内的日期自动更新为当天,一个公式就OK了
  • Docker服务发现新纪元:探索Consul的无限魅力
  • Flink SQL Cookbook on Zeppelin 部署使用
  • 赛灵思ZYNQ系列的启动过程分析
  • AIA - IMSIC之二(附IMSIC处理流程图)
  • LeetCode 203. 移除链表元素 (C++实现)
  • CSES-1132 Tree Distances I(树的直径)
  • 云宏获亚太信息通讯科技大赛二等奖