思路:
我们常见的时钟是由表盘和指针构成,所以此次我们将任务分成绘制表盘和指针两部分来完成。
相关概念
1、坐标系
在 windows 默认坐标系中,坐标原点在绘图对象(本例绘图对象是 pictureBox1)的左上角,横轴(x 轴)水平向右,纵轴(y 轴竖直向下),每经过 1 个像素加 1。
2、绘图流程
在 windows 绘图,一般分成 3 步。分别为得到绘图场景、设置画笔/画刷、绘图。
(1)设置绘图场景,我们先创建一个项目
(2)添加绘图板
选择【工具箱】->【PictureBox】,拖动到窗体中,调整 PictureBox 到窗体大小,查看右侧【属性】,可发现系统将该对象自动起名为 pictureBox1。
(3)双击绘图板,进入代码层
(3.1)我们开始创建画板:
Bitmap bitmap;//创建画图板
public Form1()
{
InitializeComponent();
bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = bitmap;
}
随后我们单独创建一个画表盘的函数:
public void Clock_back()//画表盘
{
int i;
var g = Graphics.FromImage(pictureBox1.Image);
Pen p = new Pen(Color.Black, 3);
var clock = new Rectangle(100, 0, 370, 370);//绘制一个(100,0)处开始,长370,宽370的矩形
var dot = new Rectangle(280, 180, 10, 10);
for (i = 0; i < 12; i++)//时刻标度
{
double angel = i * (Math.PI) / 6;
Point xy1 = new Point((int)(180 * Math.Cos(angel) + 285), (int)(180 * Math.Sin(angel) + 185));//圆心定义为(285,185)
Point xy2 = new Point((int)(155 * Math.Cos(angel) + 285), (int)(155 * Math.Sin(angel) + 185));
g.DrawLine(p, xy1, xy2);
}
for (i = 0; i < 60; i++)//小时刻标度
{
double angel = i * (Math.PI) / 30;
Point xy1 = new Point((int)(180 * Math.Cos(angel) + 285), (int)(180 * Math.Sin(angel) + 185));
Point xy2 = new Point((int)(170 * Math.Cos(angel) + 285), (int)(170 * Math.Sin(angel) + 185));
g.DrawLine(new Pen(Color.Blue), xy1, xy2);
}
g.DrawEllipse(p, clock);//绘制一个由clock边框定义的椭圆
g.DrawEllipse(p, dot);
g.Dispose();
}
代码解析:(无注释部分)
var g = Graphics.FromImage(pictureBox1.Image);
Pen p = new Pen(Color.Black, 3);
第一行是为了得到 pictureBox1 的绘图场景。var 是 c# 的类型关键字,说明该类型由编译器根据后续代码自动给出。
第二行定义了一个黑色的粗度为3的画笔。new 表示调用构造函数。C#规定,值类型初始化时可以直接赋值。引用类型初始化时需要用 new 调用该类型的构造函数进行初始化。
刻度的制作:
首先我们思考怎样才能绘制出刻度值,在这里我想到的办法是:绘制共用圆心的一个大圆和一个小圆。它们在同一角度下,两圆的点在同一条过圆心的直线上。
所以我们就能每隔6°和60°取一次角度,在每个圆上取出1个点,然后我们通过
g.DrawLine(p, xy1, xy2);
函数连接,就可以绘制出表盘了。函数使用方法如下
(3.2)指针绘制
public void Clock(int second,int minute,int hour)//画指针
{
var gg = Graphics.FromImage(pictureBox1.Image);
Pen s_p = new Pen(Color.Yellow, 3);
Pen m_p = new Pen(Color.Blue, 4);
Pen h_p = new Pen(Color.Red, 5);
double angel_s = second * Math.PI / 30;
double angel_m = minute * Math.PI / 30;
double angel_h = hour * Math.PI / 6 + minute * (1 / (Math.PI * 30));
Point o = new Point(285, 185);//圆心
Point s = new Point((int)(285 + 160 * Math.Sin(angel_s)), (int)(185 - 160 * Math.Cos(angel_s)));//秒针
Point m = new Point((int)(285 + 130 * Math.Sin(angel_m)), (int)(185 - 130 * Math.Cos(angel_m)));//分针
Point h = new Point((int)(285 + 100 * Math.Sin(angel_h)), (int)(185 - 100 * Math.Cos(angel_h)));//时针
gg.DrawLine(s_p, o, s);
gg.DrawLine(m_p, o, m);
gg.DrawLine(h_p, o, h);
gg.Dispose();
}
大致思路和绘制表盘是一样的,只不过这里将时针分针秒针的角度设置成了变量,后续读取系统时钟进行赋值。
此处有两点值得注意的地方
1、时针的设置
时针有12个刻度,得再加上分针走过的刻度,才能使时针不会在非整时的时候都指向整数。
2、x坐标用285+sin(angel_s),y坐标用185-cos(angel_s)求
因为在绘图板中,y轴指向下,并非我们平常认知的坐标系,所以是相反的,我们可以自己找一张白纸画一下就明白了。
(3.3)读取系统时钟,钟表运动
首先我们添加一个timer控件,其作用是没100毫秒执行一次。
双击,进入代码层,添加要执行的代码:
private void timer1_Tick(object sender, EventArgs e)
{
h = DateTime.Now.Hour;//读取系统时钟
m = DateTime.Now.Minute;
s = DateTime.Now.Second;
var gg = Graphics.FromImage(pictureBox1.Image);
gg.Clear(this.BackColor);
Clock_back();
Clock(s, m, h);
pictureBox1.Refresh();
}
启动控件:
public Form1()
{
InitializeComponent();
bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = bitmap;
timer1.Enabled = true;//启动timer
}
(3.4)
画板显示:
private void pictureBox1_Click(object sender, EventArgs e)
{
Clock_back();
Clock(s, m, h);
MessageBox.Show(s.ToString());
pictureBox1.Refresh();
}
此时我们的任务就完成了,成品效果如下:
附全部代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace whx1
{
public partial class Form1 : Form
{
Bitmap bitmap;//创建画图板
public Form1()
{
InitializeComponent();
bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = bitmap;
timer1.Enabled = true;//启动timer
}
int h, m, s;
private void timer1_Tick(object sender, EventArgs e)
{
h = DateTime.Now.Hour;//读取系统时钟
m = DateTime.Now.Minute;
s = DateTime.Now.Second;
var gg = Graphics.FromImage(pictureBox1.Image);
gg.Clear(this.BackColor);
Clock_back();
Clock(s, m, h);
pictureBox1.Refresh();
}
public void Clock_back()//画表盘
{
int i;
var g = Graphics.FromImage(pictureBox1.Image);
Pen p = new Pen(Color.Black, 3);
var clock = new Rectangle(100, 0, 370, 370);//绘制一个(100,0)处开始,长370,宽370的矩形
var dot = new Rectangle(280, 180, 10, 10);
for (i = 0; i < 12; i++)//时刻标度
{
double angel = i * (Math.PI) / 6;
Point xy1 = new Point((int)(180 * Math.Cos(angel) + 285), (int)(180 * Math.Sin(angel) + 185));//圆心定义为(285,185)
Point xy2 = new Point((int)(155 * Math.Cos(angel) + 285), (int)(155 * Math.Sin(angel) + 185));
g.DrawLine(p, xy1, xy2);
}
for (i = 0; i < 60; i++)//小时刻标度
{
double angel = i * (Math.PI) / 30;
Point xy1 = new Point((int)(180 * Math.Cos(angel) + 285), (int)(180 * Math.Sin(angel) + 185));
Point xy2 = new Point((int)(170 * Math.Cos(angel) + 285), (int)(170 * Math.Sin(angel) + 185));
g.DrawLine(new Pen(Color.Blue), xy1, xy2);
}
g.DrawEllipse(p, clock);//绘制一个由clock边框定义的椭圆
g.DrawEllipse(p, dot);
g.Dispose();
}
public void Clock(int second,int minute,int hour)//画指针
{
var gg = Graphics.FromImage(pictureBox1.Image);
Pen s_p = new Pen(Color.Yellow, 3);
Pen m_p = new Pen(Color.Blue, 4);
Pen h_p = new Pen(Color.Red, 5);
double angel_s = second * Math.PI / 30;
double angel_m = minute * Math.PI / 30;
double angel_h = hour * Math.PI / 6 + minute * (1 / (Math.PI * 30));
Point o = new Point(285, 185);//圆心
Point s = new Point((int)(285 + 160 * Math.Sin(angel_s)), (int)(185 - 160 * Math.Cos(angel_s)));//秒针
Point m = new Point((int)(285 + 130 * Math.Sin(angel_m)), (int)(185 - 130 * Math.Cos(angel_m)));//分针
Point h = new Point((int)(285 + 100 * Math.Sin(angel_h)), (int)(185 - 100 * Math.Cos(angel_h)));//时针
gg.DrawLine(s_p, o, s);
gg.DrawLine(m_p, o, m);
gg.DrawLine(h_p, o, h);
gg.Dispose();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
Clock_back();
Clock(s, m, h);
MessageBox.Show(s.ToString());
pictureBox1.Refresh();
}
}
}
ps:一只编程和写文章的小白萌新,望各路大佬多指点嘿嘿(*^▽^*)