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

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 类中,我们声明了四个私有成员函数:UpdateCounterOnDecreaseClickedOnIncreaseClickedOnResetClicked,分别用于更新计数器、处理减少按钮点击事件、处理增加按钮点击事件和处理重置按钮点击事件。我们还声明了一个 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 类的构造函数和 CreateExampleViewUpdateCounterOnDecreaseClickedOnIncreaseClickedOnResetClicked 方法。

  • 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. 引言 在前面的文章中&#xff0c;我们学习了如何在 views_examples 中添加自定义 Button 示例。在本篇文章中&#xff0c;我们将继续探索 Views 框架的应用&#xff0c;创建一个简单的计数器示例&#xff0c;以学习如何使用 Label 和 Button 控件进行交互&#xff0c;以及如…...

一步一步写线程之十六线程的安全退出之二例程

一、说明 在一篇分析了多线程的安全退出的相关机制和方式&#xff0c;那么本篇就针对前一篇的相关的分析进行举例分析。因为有些方法实现的方法类似&#xff0c;可能就不一一重复列举了&#xff0c;相关的例程主要以在Linux上的运行为主。 二、实例 线程间的同步&#xff0c…...

【Linux系列】Shell 脚本中的条件判断:`[ ]`与`[[ ]]`的比较

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

ArcGIS+MIKE21 洪水淹没分析、溃坝分析,洪水淹没动态效果

洪水淹没分析过程&#xff1a; 一、所需数据&#xff1a; 1.分析区域DEM数据 二、ArcGIS软件 1.提取分析区域DEM&#xff08;水库坝下区域&#xff09; 2.DEM栅格转点 3.计算转换后几何点的x和y坐标值&#xff08;精度20、小数位3&#xff09; 4.导出属性表&#xff0c;形式…...

Git 的基本概念和使用

Git是一个分布式版本控制系统&#xff0c;它可以帮助开发人员追踪和管理代码的修改。下面是Git的基本概念和使用方式的解释&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;Git使用仓库来存储代码和版本历史记录。仓库可以位于本地计算机上&#xff0c;也可以…...

*【每日一题 基础题】 [蓝桥杯 2024 省 B] 好数

[蓝桥杯 2024 省 B] 好数 好数 一个整数如果按从低位到高位的顺序&#xff0c;奇数位&#xff08;个位、百位、万位……&#xff09;上的数字是奇数&#xff0c;偶数位&#xff08;十位、千位、十万位……&#xff09;上的数字是偶数&#xff0c;我们就称之为“好数”。 给定一…...

对中文汉字排序的方法总结

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

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘

学习爬虫时&#xff0c;遇到如下报错&#xff1a; 报错原因&#xff1a; 正则表达式的 search 或 finditer 方法没有找到任何匹配项&#xff0c;可能是换行符处理不当等。 解决方法如下&#xff1a; 在正则表达式末尾加上re.S即可&#xff0c;re.S是一个编译标志&#xff0c…...

数据结构经典算法总复习(上卷)

第一章&#xff1a;数据结构导论 无重要考点&#xff0c;仅需了解时间复杂度。 第二章&#xff1a;线性表 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&#xff1a;现代浏览器都支持 URL 和 URLSearchParams 对象&#xff0c;可以很方便地从URL中提取参数 // 假设当前URL为 "https://example.com/?nameJohn&age30" const url new URL(window.location.href); // 或者你可以直接传入一个URL字符串 const …...

【面经】2024年软件测试面试题,精选100 道(附答案)

测试技术面试题 1、我现在有个程序&#xff0c;发现在 Windows 上运行得很慢&#xff0c;怎么判别是程序存在问题还是软硬件系统存在问题&#xff1f; 2、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 3、测试的策略有哪些&#xff1f; 4、正交表测试用…...

LabVIEW水泵性能测试系统

在现代工业应用中&#xff0c;水泵作为一种广泛使用的流体输送设备&#xff0c;其性能的可靠性对整个生产系统的稳定运行至关重要。通过LabVIEW软件配合专业硬件设备&#xff0c;设计了一套水泵性能测试系统&#xff0c;实现对各类水泵的综合性能测试与分析&#xff0c;提升水泵…...

React 第十九节 useLayoutEffect 用途使用技巧注意事项详解

1、概述 useLayoutEffect 是useEffect 的一个衍生版本&#xff0c;只是他们的执行时机不同 useLayoutEffect 用于在DOM更新执行完成之后&#xff0c;浏览器渲染绘制之前执行&#xff0c;这会阻塞浏览器的渲染&#xff1b; useEffect 的执行时机是在组件首次渲染和更新渲染之后…...

重温设计模式--2、设计模式七大原则

文章目录 1、开闭原则&#xff08;Open - Closed Principle&#xff0c;OCP&#xff09;定义&#xff1a;示例&#xff1a;好处&#xff1a; 2、里氏替换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09;定义&#xff1a;示例&#xff1a;好处&#…...

【NLP高频面题 - Transformer篇】Transformer的位置编码是如何计算的?

【NLP高频面题 - Transformer篇】Transformer的位置编码是如何计算的&#xff1f; 重要性&#xff1a;★★★ NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用…...

基于SSM(Spring + Spring MVC + MyBatis)框架构建一个图书馆仓储管理系统

基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架构建一个图书馆仓储管理系统是一个涉及多个功能模块的项目&#xff0c;包括但不限于图书管理、读者管理、借阅管理、归还管理等。 1. 环境准备 确保你已经安装了以下工具和环境&#xff1a; Java Developmen…...

web的五个Observer API

IntersectionObserver&#xff1a; 一个元素从不可见到可见&#xff0c;从可见到不可见 ??IntersectionObserver是一种浏览器提供的 JavaScript API&#xff0c;用于监测元素与视窗的交叉状态。它可以告诉开发者一个元素是否进入或离开视窗&#xff0c;以及两者的交叉区域的…...

Java基础:抽象类与接口

1、抽象类和接口的定义&#xff1a; &#xff08;1&#xff09;抽象类主要用来抽取子类的通用特性&#xff0c;作为子类的模板&#xff0c;它不能被实例化&#xff0c;只能被用作为子类的超类。 &#xff08;2&#xff09;接口是抽象方法的集合&#xff0c;声明了一系列的方法…...

llama.cpp:PC端测试 MobileVLM -- 电脑端部署图生文大模型

llama.cpp&#xff1a;PC端测试 MobileVLM 1.环境需要2.构建项目3.PC测试 1.环境需要 以下是经实验验证可行的环境参考&#xff0c;也可尝试其他版本。 &#xff08;1&#xff09;PC&#xff1a;Ubuntu 22.04.4 &#xff08;2&#xff09;软件环境&#xff1a;如下表所示 工…...

Web前端基础知识(一)

前端是构建网页的一部分&#xff0c;负责用户在浏览器中看到和与之交互的内容。 网页是在浏览器中呈现内容的文档或页面。 通常&#xff0c;网页使用HTML、CSS、JavaScript(JS)组成。 HTML:定义了页面的结构和内容。包括文本、图像、链接等。 CSS&#xff1a;定义页面的样式…...

3分钟解锁音乐自由:NCMconverter让你的加密音乐随处播放

3分钟解锁音乐自由&#xff1a;NCMconverter让你的加密音乐随处播放 【免费下载链接】NCMconverter NCMconverter将ncm文件转换为mp3或者flac文件 项目地址: https://gitcode.com/gh_mirrors/nc/NCMconverter 你是否曾遇到过这样的情况&#xff1a;从音乐平台下载了喜欢…...

让 AI 代理拥有“专业技能包“:Microsoft Agent Skills厩

一、核心问题及解决方案&#xff08;按踩坑频率排序&#xff09; 问题 1&#xff1a;误删他人持有锁——最基础也最易犯的漏洞 成因&#xff1a;释放锁时未做身份校验&#xff0c;直接执行 DEL 命令删除键。典型场景&#xff1a;服务 A 持有锁后&#xff0c;业务逻辑耗时超过锁…...

中科院FlowPIE:AI实现科学创意自动孵化突破研究范式创新

这项由中国科学院深圳先进技术研究院联合大连理工大学等多家科研院所开展的研究&#xff0c;发表于2026年3月31日的arXiv预印本平台&#xff08;论文编号&#xff1a;arXiv:2603.29557v1&#xff09;&#xff0c;为科学创意生成领域带来了革命性突破。有兴趣深入了解的读者可以…...

Ostrakon-VL终端惊艳效果:像素UI下支持键盘快捷键(F5刷新/F6扫描)

Ostrakon-VL终端惊艳效果&#xff1a;像素UI下支持键盘快捷键&#xff08;F5刷新/F6扫描&#xff09; 1. 像素特工终端概览 这是一个基于Ostrakon-VL-8B多模态大模型开发的Web交互终端&#xff0c;专为零售与餐饮场景优化。与传统工业级UI不同&#xff0c;我们采用了高饱和度…...

YOLOv11与PP-DocLayoutV3对比:目标检测与文档版面分析的技术异同

YOLOv11与PP-DocLayoutV3对比&#xff1a;目标检测与文档版面分析的技术异同 最近在和朋友聊起计算机视觉项目时&#xff0c;发现一个挺有意思的现象。有人拿着一个号称“地表最强”的通用目标检测模型&#xff0c;信心满满地想去处理一份复杂的扫描版PDF&#xff0c;结果却碰…...

二极管工作原理与应用全解析

1. 二极管基础认知&#xff1a;电子世界的单向阀门我第一次接触二极管是在大学电子实验课上&#xff0c;当时看着这个小小的玻璃管状元件&#xff0c;很难想象它能在电路中起到如此关键的作用。直到亲眼目睹它只允许电流单向通过的特性&#xff0c;才真正理解为什么工程师们称它…...

SQL 单表操作全解

SQL 单表操作全解 本文所有语法和实例&#xff0c;均基于开发最常用的users用户表&#xff0c;表结构完全符合生产规范&#xff0c;后续所有操作均围绕此表展开&#xff1a; CREATE TABLE IF NOT EXISTS users (id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 用户ID&#x…...

兄弟同心,其利断金:Tomcat、Nginx 与 Node.js 的“三重奏”

写在前面初学后端开发时&#xff0c;我一直困惑一个问题&#xff1a;Tomcat、Nginx、Node.js&#xff0c;它们之间到底是什么关系&#xff1f;刚开始用 Spring Boot&#xff0c;发现里面集成了 Tomcat&#xff0c;启动项目后访问 localhost:8080 就能调接口。那时我以为&#x…...

详细解析Spring如何解决循环依赖问题居

AI训练存储选型的演进路线 第一阶段&#xff1a;单机直连时代 早期的深度学习数据集较小&#xff0c;模型训练通常在单台服务器或单张GPU卡上完成。此时直接将数据存储在训练机器的本地NVMe SSD/HDD上。 其优势在于IO延迟最低&#xff0c;吞吐量极高&#xff0c;也就是“数据离…...

UnifiedLog:嵌入式统一日志框架设计与实践

1. UnifiedLog&#xff1a;面向嵌入式系统的统一日志框架设计与工程实践在资源受限的嵌入式系统开发中&#xff0c;调试信息输出长期面临协议割裂、接口冗余、资源争用和维护成本高等现实问题。典型场景下&#xff0c;开发者往往需为串口&#xff08;UART&#xff09;、MQTT、L…...