从本篇文章开始,边学边练开发一个秒表应用,本文是本系列的第一篇:绘制表盘。先看演示视频:

秒表应用开发(1)

准备布局

内容很简单,一个Text组件加上自定义的秒表组件。


<?xml version="1.0" encoding="utf-8"?><DirectionalLayout    xmlns:ohos="http://schemas.huawei.com/res/ohos"    ohos:height="match_parent"    ohos:width="match_parent"    ohos:orientation="vertical"    ohos:alignment="center">
    <Text        ohos:id="$+id:gui_thread_time"        ohos:height="match_content"        ohos:width="match_content"        ohos:background_element="$graphic:background_ability_main"        ohos:layout_alignment="horizontal_center"        ohos:text="22:20:20.123"        ohos:text_size="50fp"        ohos:text_color="#0000FF"        />    <xwg.harmony.stopwatch.AnalogStopWatch        ohos:id="$+id:analog_stop_watch"        ohos:height="400vp"        ohos:width="match_parent"        /></DirectionalLayout>

绘制表盘

代码虽长,但并不难。AnalogStopWath类继承自Component类并实现了Component.DrawTask接口。但目前实现了绘制表盘和秒针功能。

从第3行到第21行重载了Component的构造函数;第24~26行实现了DrawTask的onDraw操作。目前只调用了一个drawPanel方法,将来会调用其他方法。

第28~31的setSecond方法用于指定当前的秒数值。秒数值更新后会调用超类的invalidate方法启动描画过程。

​​​​​​​
public class AnalogStopWatch extends Component implements Component.DrawTask {    double second = 0;    public AnalogStopWatch(Context context) {        super(context);        Initialize(null);    }
    public AnalogStopWatch(Context context, AttrSet attrSet) {        super(context, attrSet);        Initialize(attrSet);    }
    public AnalogStopWatch(Context context, AttrSet attrSet, String styleName) {        super(context, attrSet, styleName);        Initialize(attrSet);    }
    public AnalogStopWatch(Context context, AttrSet attrSet, int resId) {        super(context, attrSet, resId);        Initialize(attrSet);    }
    @Override    public void onDraw(Component component, Canvas canvas) {        drawPanel(canvas);    }
    public void setSecond(double sec) {        second = sec;        invalidate();    }
    private void drawPanel(Canvas canvas){        Paint paint = new Paint();        paint.setColor(Color.WHITE);        RectFloat bound = getBoundRect();        float radius = bound.getWidth() / 2;        float len5sec = radius / 5;        float len1sec = radius / 10;        float len02sec = radius / 20;        Point center = bound.getCenter();        canvas.drawOval(bound, paint);        paint.setColor(Color.BLACK);        for(int i = 0; i < 360; i++){            float insideRaduis = radius;            if ((i % 30)==0){                insideRaduis -= len5sec;                paint.setStrokeWidth(radius / 60);            }            else if((i % 5)==0){                insideRaduis -= len1sec;                paint.setStrokeWidth(radius / 80);            }            else{                insideRaduis -= len02sec;                paint.setStrokeWidth(radius / 120);            }            drawRadius(canvas, paint, insideRaduis, radius, i);        }        paint.setColor(Color.RED);        paint.setStrokeWidth(radius / 40);        paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);        drawRadius(canvas, paint, 0, radius * 0.9f, second * 6);        float oval_radius = radius / 20;        canvas.drawOval(new RectFloat(center.getPointX() - oval_radius, center.getPointY() - oval_radius,                                    center.getPointX() + oval_radius, center.getPointY() + oval_radius),                        paint);    }        private void drawRadius(Canvas canvas, Paint paint, float from, float to, double degree){        double angle = Math.PI * degree / 180;        double sin = Math.sin(angle);        double cos = Math.cos(angle);        Point center = getBoundRect().getCenter();        canvas.drawLine(new Point(center.getPointX() + (float)(from * sin),                        center.getPointY() - (float)(from * cos)),                        new Point(center.getPointX() + (float)(to * sin),                        center.getPointY() - (float)(to * cos)),                        paint);    }
    private RectFloat getBoundRect(){        float width = getWidth();        float height = getHeight();        float size = Math.min(width, height);        float x_padding = (width - size) / 2;        float y_padding = (height - size) / 2;        return new RectFloat(x_padding, y_padding, width - x_padding, height - y_padding);    }
    private void Initialize(AttrSet attrSet){        addDrawTask(this);    }}

drawRadius用于绘制各种径向直线,如刻度线,指针等。角度是以12点钟其实都度数单位,这种方式最适合表示时间。

下图是描画结果:


参考代码

完整代码可以从以下链接下载:

https://github.com/xueweiguo/Harmony/tree/master/StopWatch

作者著作介绍

《实战Python设计模式》是作者去年3月份出版的技术书籍,该书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。


觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!

自学鸿蒙应用开发(43)- 秒表应用开发(1)相关推荐

  1. 自学鸿蒙应用开发(44)- 秒表应用开发(2)

    经过几天的开发,秒表应用终于初具规模了,先看执行效果: 秒表应用开发2 指针式秒表组件 下面是自定义指针式模拟秒表组件的实现代码.具体内容参见注释. //指针式秒表组件类public class An ...

  2. 4 年开发 43 款软件,这位乡村教师火了

    整理 | 王晓曼 出品 | 程序人生 (ID:coder _life) 今天,一则#乡村教师自学编程4年开发43款软件#的话题冲上微博热搜.主人公彭龙是四川泸州一名乡村数学教师,4年多来他自学编程,开 ...

  3. 自学python还是报班-转行Python开发自学还是报班?老男孩全日制学习

    很多朋友在转行时非常慎重,在很多人眼里学Python开发就是敲敲代码而已,这样的想法磨灭了很多想转行人的热情.其实Python工程师并不是一份枯燥工作,它有多种机会去做很多事情,比如游戏开发.人工智能 ...

  4. 梅科尔工作室——鸿蒙设备开发实战004:内核开发

    目录 华为云14天鸿蒙设备开发培训Day4:内核开发 任务管理 任务管理的简介 任务相关的概念 任务的调度机制 实现任务的管理 实验结果与扩展实验 软件定时器 软件定时器的基本概念 软件定时器的运作机 ...

  5. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石

    文章目录 1.1 休眠与唤醒 1.1.1 适用场景 1.1.2 内核函数 1.1.2.1 休眠函数 1.1.2.2 唤醒函数 19.1.3 驱动框架 1.1.4 编程 1.1.4.1 驱动程序关键代码 ...

  6. 鸿蒙OS Hi3861的芯片实际开发中遇到的问题

    鸿蒙OS Hi3861的芯片实际开发中遇到的问题 优点: 比较适合开发者快速开发,上面的硬件操作的函数封装很简单,非常适合初学者使用封装好的函数调用硬件管脚,比如I2c gpio spi sdio 都 ...

  7. python测试开发自学教程-自动化平台测试开发:Python测试开发实战_PDF电子书

    因资源下载地址容易失效,请加微信号359049049直接领取,直接发最新下载地址. 前言 ======================================================= ...

  8. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(一) 嵌入式Linux开发基本概念以及开发流程介绍

    文章目录 1.linux开发初了解 1.1 嵌入式Linux开发的基本概念 1.1.1关于Git的背景介绍 1.1.2关于repo的背景介绍 1.1 3 一些关于此背景知识的介绍 1.1.4关于Lin ...

  9. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(八)IMX6ULL开发板编译第一个程序以及驱动

    文章目录 1. IMX6ULL开发板初次操作 1.1 100ask_imx6ull开发板硬件资源简介 1.1.1 100ask imx6ull mini开发板 1.2 100ask_imx6ull开发 ...

最新文章

  1. Oracle的口令文件(passwordfile)的讲解(摘录)
  2. HDU3338 Kakuro Extension(最大流+思维构图)
  3. JAVA8 Stream方法使用详解Filter、map等用法(一)
  4. PHP中的逆波兰式应用
  5. (一)nodejs循序渐进-nodejs环境安装(基础篇)
  6. linux vim tag,Vim基础知识之ctags 及 Taglist 插件
  7. abaqus失效单元删除_Abaqus实例教学2-Failure Model
  8. JS 中通过对象关联实现『继承』
  9. “跨国视频造假窝点”曝光!这个大规模数据集,帮AI揪出99%换脸视频
  10. Windows终端(WT)添加conda命令行
  11. 老板要我开发一个简单的工作流引擎 !
  12. Private Bytes,Working Set,Virtual Size的区别
  13. 数据时代建设医疗数据,主要有哪些意义?
  14. OpenGL Android课程六:介绍纹理过滤
  15. 戴尔云客户端:三大发力点实现高速增长
  16. 数据中心机房有哪些等级,国内外的评级标准?
  17. FPGA EMMC HS400模式verilog驱动开发
  18. php做excel导入word,php如何将excel表格插入到word文档
  19. 取消AsyncTask
  20. NAT功能介绍及配置应用

热门文章

  1. 用excel制作工程项目进度图(甘特图)
  2. centos7 rabbitMQ集群搭建
  3. 全球与中国光纤输出半导体激光器市场现状及未来发展趋势
  4. 使用poi-tl根据word模板生成word文件——解决生成的表格里数据行有小标题的这种需求
  5. 本地硬盘如何重装系统Win7教程
  6. 疯狂java讲义第16章多线程课后习题答案
  7. 获取工作组作为域名的方法
  8. 诺基亚N95游戏下载大全
  9. 国际化程度加深,国内期市引入QFII呼声再起
  10. PCB设计技巧百问(合集)