Chromium GN 目标指南 - view_example 计数器示例 (七)
1. 引言
在前面的文章中,我们学习了如何在 views_examples
中添加自定义 Button 示例。在本篇文章中,我们将继续探索 Views 框架的应用,创建一个简单的计数器示例,以学习如何使用 Label 和 Button 控件进行交互,以及如何更新 UI 状态。
2. 创建计数器示例
为了创建计数器示例,我们需要创建新的头文件和源文件,并在其中定义计数器类和相关的示例代码。
2.1 创建头文件
首先,我们在 ui/views/examples/
目录下创建一个名为 counter_example.h
的头文件,并在其中添加以下代码:
#ifndef UI_VIEWS_EXAMPLES_COUNTER_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_COUNTER_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 CounterExample : public ExampleBase {public:CounterExample();CounterExample(const CounterExample&) = delete;CounterExample& operator=(const CounterExample&) = delete;~CounterExample() override = default;// ExampleBase:void CreateExampleView(View* container) override;private:void UpdateCounter();void OnDecreaseClicked();void OnIncreaseClicked();void OnResetClicked();int counter_;raw_ptr<views::Label> counter_label_ = nullptr;raw_ptr<views::Label> status_label_ = nullptr;
};} // namespace views::examples#endif // UI_VIEWS_EXAMPLES_COUNTER_EXAMPLE_H_
这段代码定义了一个名为 CounterExample
的类,它继承自 ExampleBase
。在 CounterExample
类中,我们声明了四个私有成员函数:UpdateCounter
、OnDecreaseClicked
、OnIncreaseClicked
和 OnResetClicked
,分别用于更新计数器、处理减少按钮点击事件、处理增加按钮点击事件和处理重置按钮点击事件。我们还声明了一个 int
类型的成员变量 counter_
用于存储计数器的值,以及两个 raw_ptr<views::Label>
类型的成员变量 counter_label_
和 status_label_
,分别用于显示计数器的值和状态信息。
2.2 创建源文件
接下来,我们在 ui/views/examples/
目录下创建一个名为 counter_example.cc
的源文件,并在其中添加以下代码:
#include "ui/views/examples/counter_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/controls/label.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"namespace views::examples {CounterExample::CounterExample() : ExampleBase("Counter Example"), counter_(0) {}void CounterExample::CreateExampleView(View* container) {// 使用水平布局auto* layout = new views::BoxLayout(views::BoxLayout::Orientation::kHorizontal, gfx::Insets(10), // 边距20); // 组件间距container->SetLayoutManager(std::unique_ptr<views::BoxLayout>(layout));// 减少按钮auto* decrease_button = new views::MdTextButton(base::BindRepeating(&CounterExample::OnDecreaseClicked,base::Unretained(this)),u"-");decrease_button->SetStyle(ui::ButtonStyle::kText);container->AddChildView(decrease_button);// 计数显示标签counter_label_ = new views::Label(u"0");counter_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);counter_label_->SetSize(gfx::Size(50, 0)); // 设置标签大小container->AddChildView(counter_label_);// 增加按钮auto* increase_button = new views::MdTextButton(base::BindRepeating(&CounterExample::OnIncreaseClicked,base::Unretained(this)),u"+");increase_button->SetStyle(ui::ButtonStyle::kText);container->AddChildView(increase_button);// 重置按钮auto* reset_button = new views::MdTextButton(base::BindRepeating(&CounterExample::OnResetClicked,base::Unretained(this)),u"Reset");reset_button->SetStyle(ui::ButtonStyle::kTonal);container->AddChildView(reset_button);// 状态标签status_label_ = new views::Label(u"Counter initialized");container->AddChildView(status_label_);
}void CounterExample::UpdateCounter() {counter_label_->SetText(base::UTF8ToUTF16(std::to_string(counter_)));LOG(INFO) << "Counter value: " << counter_;
}void CounterExample::OnDecreaseClicked() {counter_--;UpdateCounter();status_label_->SetText(u"Counter decreased");
}void CounterExample::OnIncreaseClicked() {counter_++;UpdateCounter();status_label_->SetText(u"Counter increased");
}void CounterExample::OnResetClicked() {counter_ = 0;UpdateCounter();status_label_->SetText(u"Counter reset");
}} // namespace views::examples
这段代码实现了 CounterExample
类的构造函数和 CreateExampleView
、UpdateCounter
、OnDecreaseClicked
、OnIncreaseClicked
、OnResetClicked
方法。
CounterExample::CounterExample()
: 构造函数,调用了父类ExampleBase
的构造函数,并设置了示例的名称为 "Counter Example",同时初始化counter_
为 0。CounterExample::CreateExampleView(View* container)
: 这个方法负责创建并添加计数器相关的控件到container
中。- 首先,它创建了一个水平布局管理器
BoxLayout
,并将其设置给container
。 - 然后,它创建了四个按钮:
decrease_button
: 减少按钮,点击后会调用OnDecreaseClicked
方法。increase_button
: 增加按钮,点击后会调用OnIncreaseClicked
方法。reset_button
: 重置按钮,点击后会调用OnResetClicked
方法。
- 接着创建了一个
Label
控件counter_label_
,用于显示计数器的值,设置其水平对齐方式为居中,并设置了最小宽度为50像素。 - 最后创建了一个
Label
控件status_label_
,用于显示计数器的状态信息。
- 首先,它创建了一个水平布局管理器
CounterExample::UpdateCounter()
: 这个方法用于更新counter_label_
的文本内容,将其设置为当前计数器的值,并在日志中输出当前计数器的值。CounterExample::OnDecreaseClicked()
: 当decrease_button
被点击时,这个方法会被调用。它会将计数器counter_
的值减1,调用UpdateCounter
方法更新counter_label_
的显示,并将status_label_
的文本设置为 "Counter decreased"。CounterExample::OnIncreaseClicked()
: 当increase_button
被点击时,这个方法会被调用。它会将计数器counter_
的值加1,调用UpdateCounter
方法更新counter_label_
的显示,并将status_label_
的文本设置为 "Counter increased"。CounterExample::OnResetClicked()
: 当reset_button
被点击时,这个方法会被调用。它会将计数器counter_
的值重置为0,调用UpdateCounter
方法更新counter_label_
的显示,并将status_label_
的文本设置为 "Counter reset"。
3. 修改 BUILD.gn 文件
为了将我们的计数器示例添加到构建系统中,我们需要修改 ui/views/examples/BUILD.gn
文件,将我们新创建的源文件添加到 examples
目标的 sources
属性中。
打开 ui/views/examples/BUILD.gn
文件,找到 views_examples_lib
部分,并在 sources
列表中添加以下两行:
"counter_example.cc",
"counter_example.h",
4. 注册示例
最后,我们需要在 ui/views/examples/create_examples.cc
文件中注册我们的计数器示例,这样 views_examples
程序才能找到并显示它。
打开 ui/views/examples/create_examples.cc
文件,找到 CreateExamples
函数,并在 examples
向量中添加以下代码:
examples.push_back(std::make_unique<CounterExample>());
修改后的 CreateExamples
函数应该类似于这样:
ExampleVector CreateExamples() {ExampleVector examples;// ... 其他示例 ...examples.push_back(std::make_unique<MyCustomButtonExample>());examples.push_back(std::make_unique<CounterExample>());// ... 其他示例 ...return examples;
}
5. 重新编译并运行
完成以上步骤后,我们需要重新编译 views_examples
目标。在 Chromium 源码的 src
目录下执行以下命令:
autoninja -C out/Default views_examples
编译完成后,运行 views_examples
:
./out/Default/views_examples
如果一切顺利,你将在 "Views Examples" 窗口中看到一个新的标签页 "Counter Example",点击该标签页,你将看到我们自定义的计数器,包括一个显示计数器值的 Label,以及减少、增加和重置三个按钮。点击不同的按钮,计数器的值会相应地改变,同时下方的 Label 会显示相应的状态信息。
6. 结语
在本篇文章中,我们学习了如何在 views_examples
中添加计数器示例,包括创建头文件和源文件、修改 BUILD.gn
文件、注册示例以及重新编译和运行。通过这个过程,我们学习了如何使用 Label 和 Button 控件进行交互,以及如何更新 UI 状态。
希望这篇文章能够帮助你更好地理解 Chromium 的 Views 框架和 GN 构建系统。在接下来的文章中,我们将继续探索 Chromium 和 GN 的更多高级用法。
相关文章:

Chromium GN 目标指南 - view_example 计数器示例 (七)
1. 引言 在前面的文章中,我们学习了如何在 views_examples 中添加自定义 Button 示例。在本篇文章中,我们将继续探索 Views 框架的应用,创建一个简单的计数器示例,以学习如何使用 Label 和 Button 控件进行交互,以及如…...
一步一步写线程之十六线程的安全退出之二例程
一、说明 在一篇分析了多线程的安全退出的相关机制和方式,那么本篇就针对前一篇的相关的分析进行举例分析。因为有些方法实现的方法类似,可能就不一一重复列举了,相关的例程主要以在Linux上的运行为主。 二、实例 线程间的同步,…...

【Linux系列】Shell 脚本中的条件判断:`[ ]`与`[[ ]]`的比较
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

ArcGIS+MIKE21 洪水淹没分析、溃坝分析,洪水淹没动态效果
洪水淹没分析过程: 一、所需数据: 1.分析区域DEM数据 二、ArcGIS软件 1.提取分析区域DEM(水库坝下区域) 2.DEM栅格转点 3.计算转换后几何点的x和y坐标值(精度20、小数位3) 4.导出属性表,形式…...
Git 的基本概念和使用
Git是一个分布式版本控制系统,它可以帮助开发人员追踪和管理代码的修改。下面是Git的基本概念和使用方式的解释: 仓库(Repository):Git使用仓库来存储代码和版本历史记录。仓库可以位于本地计算机上,也可以…...
*【每日一题 基础题】 [蓝桥杯 2024 省 B] 好数
[蓝桥杯 2024 省 B] 好数 好数 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一…...

对中文汉字排序的方法总结
写在前面 在各个系统中,都随处可见根据某个字段进行升序(ASC)或降序(DESC)进行排序展示。但进行中文汉字排序和查找的时候,对中文汉字的排序和查找结果往往都是错误的。 为了尽量提供全面的解决方法,本文会从各个层面出发告知有需要的人对应…...

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘
学习爬虫时,遇到如下报错: 报错原因: 正则表达式的 search 或 finditer 方法没有找到任何匹配项,可能是换行符处理不当等。 解决方法如下: 在正则表达式末尾加上re.S即可,re.S是一个编译标志,…...

数据结构经典算法总复习(上卷)
第一章:数据结构导论 无重要考点,仅需了解时间复杂度。 第二章:线性表 1.获得线性表第i个元素 void GetElem_sq(SqList L, int i, ElemType &e) {if (i<1 || i>L.length) ErrorMsg("Invalid i value"); //注意错误监…...
JS获取URL中参数值的4种方法
方法1:现代浏览器都支持 URL 和 URLSearchParams 对象,可以很方便地从URL中提取参数 // 假设当前URL为 "https://example.com/?nameJohn&age30" const url new URL(window.location.href); // 或者你可以直接传入一个URL字符串 const …...

【面经】2024年软件测试面试题,精选100 道(附答案)
测试技术面试题 1、我现在有个程序,发现在 Windows 上运行得很慢,怎么判别是程序存在问题还是软硬件系统存在问题? 2、什么是兼容性测试?兼容性测试侧重哪些方面? 3、测试的策略有哪些? 4、正交表测试用…...

LabVIEW水泵性能测试系统
在现代工业应用中,水泵作为一种广泛使用的流体输送设备,其性能的可靠性对整个生产系统的稳定运行至关重要。通过LabVIEW软件配合专业硬件设备,设计了一套水泵性能测试系统,实现对各类水泵的综合性能测试与分析,提升水泵…...
React 第十九节 useLayoutEffect 用途使用技巧注意事项详解
1、概述 useLayoutEffect 是useEffect 的一个衍生版本,只是他们的执行时机不同 useLayoutEffect 用于在DOM更新执行完成之后,浏览器渲染绘制之前执行,这会阻塞浏览器的渲染; useEffect 的执行时机是在组件首次渲染和更新渲染之后…...

重温设计模式--2、设计模式七大原则
文章目录 1、开闭原则(Open - Closed Principle,OCP)定义:示例:好处: 2、里氏替换原则(Liskov Substitution Principle,LSP)定义:示例:好处&#…...

【NLP高频面题 - Transformer篇】Transformer的位置编码是如何计算的?
【NLP高频面题 - Transformer篇】Transformer的位置编码是如何计算的? 重要性:★★★ NLP Github 项目: NLP 项目实践:fasterai/nlp-project-practice 介绍:该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用…...
基于SSM(Spring + Spring MVC + MyBatis)框架构建一个图书馆仓储管理系统
基于SSM(Spring Spring MVC MyBatis)框架构建一个图书馆仓储管理系统是一个涉及多个功能模块的项目,包括但不限于图书管理、读者管理、借阅管理、归还管理等。 1. 环境准备 确保你已经安装了以下工具和环境: Java Developmen…...
web的五个Observer API
IntersectionObserver: 一个元素从不可见到可见,从可见到不可见 ??IntersectionObserver是一种浏览器提供的 JavaScript API,用于监测元素与视窗的交叉状态。它可以告诉开发者一个元素是否进入或离开视窗,以及两者的交叉区域的…...
Java基础:抽象类与接口
1、抽象类和接口的定义: (1)抽象类主要用来抽取子类的通用特性,作为子类的模板,它不能被实例化,只能被用作为子类的超类。 (2)接口是抽象方法的集合,声明了一系列的方法…...
llama.cpp:PC端测试 MobileVLM -- 电脑端部署图生文大模型
llama.cpp:PC端测试 MobileVLM 1.环境需要2.构建项目3.PC测试 1.环境需要 以下是经实验验证可行的环境参考,也可尝试其他版本。 (1)PC:Ubuntu 22.04.4 (2)软件环境:如下表所示 工…...
Web前端基础知识(一)
前端是构建网页的一部分,负责用户在浏览器中看到和与之交互的内容。 网页是在浏览器中呈现内容的文档或页面。 通常,网页使用HTML、CSS、JavaScript(JS)组成。 HTML:定义了页面的结构和内容。包括文本、图像、链接等。 CSS:定义页面的样式…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...