模拟时钟 - 在时钟上绘制时钟 [英] Analog Clock - Draw clocks arm over a Label
问题描述
我使用WinForms创建一个时钟。问题是时钟手正在我的面板/标签下。我试图在我的面板/标签上绘制手,但我没有成功。我也尝试将我的面板/标签移动到后面,并将手放在前面,这也不能很好地工作。我也尝试做一些像这样的 panel_digital_Timer.Parent = pictureBox1
,它制作了一个透明面板。我怎样才能将时钟放在面板/标签前面?
public partial class Form1:Form
{
private Bitmap bmp;
private int angle = 0;
private int counter_Time;
public Form1()
{
InitializeComponent();
$ b $ private void Form1_Load(object sender,EventArgs e)
{
pictureBox1.Paint + = PictureBox1_Paint;
bmp = Properties.Resources.Clock_Arm;
//pictureBoxOverlay.BackColor = Color.Transparent;
////更改父母的覆盖图片PictureBox ...
pictureBoxOverlay.Parent = pictureBox1;
panel_digital_Timer.BackColor = Color.Transparent;
$ b $ private void PictureBox1_Paint(object sender,PaintEventArgs e)
{
var rbmp = rotateCenter(bmp,angle);
e.Graphics.TranslateTransform((pictureBox1.Width - rbmp.Width)/ 2,
(pictureBox1.Height - rbmp.Height)/ 2);
e.Graphics.DrawImage(rbmp,0,0);
e.Graphics.ResetTransform();
}
///< summary>
///将输入图像围绕中心旋转θ度。
///< / summary>
public static Bitmap rotateCenter(Bitmap bmpSrc,float theta)
{
Matrix mRotate = new Matrix();
//mRotate.Translate(bmpSrc.Width / -2,bmpSrc.Height / -2,MatrixOrder.Append);
mRotate.Translate(bmpSrc.Width / -2,-bmpSrc.Height,MatrixOrder.Append);
mRotate.RotateAt(theta,new Point(0,0),MatrixOrder.Append);
using(GraphicsPath gp = new GraphicsPath())
{//通过旋转矩阵变换图像点
gp.AddPolygon(new Point [] {new Point(0,0),new Point (bmpSrc.Width,0),new Point(0,bmpSrc.Height)});
gp.Transform(mRotate);
PointF [] pts = gp.PathPoints;
//创建包含旋转源图像的目标位图
Rectangle bbox = boundingBox(bmpSrc,mRotate);
位图bmpDest =新位图((int)(bbox.Width * 2),(int)(bbox.Height * 2));
使用(Graphics gDest = Graphics.FromImage(bmpDest))
{//将源绘制到dest
Matrix mDest = new Matrix();
//mDest.Translate(bmpDest.Width / 2,bmpDest.Height / 2,MatrixOrder.Append);
mDest.Translate(bmpDest.Width / 2,bmpDest.Height / 2,MatrixOrder.Append);
gDest.Transform = mDest;
gDest.DrawImage(bmpSrc,pts);
// drawAxes(gDest,Color.Red,0,0,1,100,);
return bmpDest;
$ b private static Rectangle boundingBox(Image img,Matrix matrix)
{
GraphicsUnit gu = new GraphicsUnit() ;
Rectangle rImg = Rectangle.Round(img.GetBounds(ref gu));
//转换图像的四个点,以获得调整大小的边界框。
Point topLeft = new Point(rImg.Left,rImg.Top);
点topRight =新点(rImg.Right,rImg.Top);
Point bottomRight = new Point(rImg.Right,rImg.Bottom);
Point bottomLeft = new Point(rImg.Left,rImg.Bottom);
Point [] points = new Point [] {topLeft,topRight,bottomRight,bottomLeft};
GraphicsPath gp = new GraphicsPath(points,
new byte [] {(byte)PathPointType.Start,(byte)PathPointType.Line,(byte)PathPointType.Line,(byte)PathPointType.Line}) ;
gp.Transform(matrix);
return Rectangle.Round(gp.GetBounds());
private void Timer_StopClock_Tick(object sender,EventArgs e)
{
if(counter_Time == 360)
{
counter_Time = 0;
}
else
{
counter_Time + = 15;
}
angle = counter_Time;
// angle + = counter_Time;
Console.WriteLine(counter_Time);
pictureBox1.Invalidate();
下载项目:
问题
不要使用 TextBox
来显示文本,自己绘制文本。
您在
I'm using WinForms to create a clock. The problem is the clocks hand is going under my panel/label. I tried to paint the hand on top of my panel/label but I wasn't successful. I also tried moving my panel/label to the back and the hand to the front and that didn't work well either. I also tried doing something like this panel_digital_Timer.Parent = pictureBox1
which made a transparent panel. How can i move the clocks hand in front of my panel/label?
public partial class Form1 : Form
{
private Bitmap bmp;
private int angle = 0;
private int counter_Time;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Paint += PictureBox1_Paint;
bmp = Properties.Resources.Clock_Arm;
//pictureBoxOverlay.BackColor = Color.Transparent;
//// Change parent for overlay PictureBox...
pictureBoxOverlay.Parent = pictureBox1;
panel_digital_Timer.BackColor = Color.Transparent;
}
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
var rbmp = rotateCenter(bmp, angle);
e.Graphics.TranslateTransform((pictureBox1.Width - rbmp.Width) / 2,
(pictureBox1.Height - rbmp.Height) / 2);
e.Graphics.DrawImage(rbmp, 0, 0);
e.Graphics.ResetTransform();
}
/// <summary>
/// Rotates the input image by theta degrees around center.
/// </summary>
public static Bitmap rotateCenter(Bitmap bmpSrc, float theta)
{
Matrix mRotate = new Matrix();
//mRotate.Translate(bmpSrc.Width / -2, bmpSrc.Height / -2, MatrixOrder.Append);
mRotate.Translate(bmpSrc.Width / -2, -bmpSrc.Height, MatrixOrder.Append);
mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);
using (GraphicsPath gp = new GraphicsPath())
{ // transform image points by rotation matrix
gp.AddPolygon(new Point[] { new Point(0, 0), new Point(bmpSrc.Width, 0), new Point(0, bmpSrc.Height) });
gp.Transform(mRotate);
PointF[] pts = gp.PathPoints;
// create destination bitmap sized to contain rotated source image
Rectangle bbox = boundingBox(bmpSrc, mRotate);
Bitmap bmpDest = new Bitmap((int)(bbox.Width * 2), (int)(bbox.Height * 2));
using (Graphics gDest = Graphics.FromImage(bmpDest))
{ // draw source into dest
Matrix mDest = new Matrix();
//mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
gDest.Transform = mDest;
gDest.DrawImage(bmpSrc, pts);
//drawAxes(gDest, Color.Red, 0, 0, 1, 100, "");
return bmpDest;
}
}
}
private static Rectangle boundingBox(Image img, Matrix matrix)
{
GraphicsUnit gu = new GraphicsUnit();
Rectangle rImg = Rectangle.Round(img.GetBounds(ref gu));
// Transform the four points of the image, to get the resized bounding box.
Point topLeft = new Point(rImg.Left, rImg.Top);
Point topRight = new Point(rImg.Right, rImg.Top);
Point bottomRight = new Point(rImg.Right, rImg.Bottom);
Point bottomLeft = new Point(rImg.Left, rImg.Bottom);
Point[] points = new Point[] { topLeft, topRight, bottomRight, bottomLeft };
GraphicsPath gp = new GraphicsPath(points,
new byte[] { (byte)PathPointType.Start, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line });
gp.Transform(matrix);
return Rectangle.Round(gp.GetBounds());
}
private void Timer_StopClock_Tick(object sender, EventArgs e)
{
if (counter_Time == 360)
{
counter_Time = 0;
}
else
{
counter_Time += 15;
}
angle = counter_Time;
//angle += counter_Time;
Console.WriteLine(counter_Time);
pictureBox1.Invalidate();
}
}
Download Project: http://www.filedropper.com/clockprojectquestion
Goal
Problem
Don't use a TextBox
to show the text, draw the text yourself.
The drawings which you draw on the Graphics
object of a Control
will be drawn on surface of the control and can not be drawn over the child controls or other stacked controls. So in above code instead of using a TextBox
to show the text, you should draw text using TextRenderer.DrawText
.
Example
Handle Tick
event of a timer with Interval
set to 1000 and call pictureBox1.Invalidate();
in the Tick
event handler. Then in handle Paint
event of the picture box this way:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.White);
var r1 = this.pictureBox1.ClientRectangle;
r1.Inflate(-3, -3);
g.DrawEllipse(Pens.Black, r1);
var r2 = r1;
r2.Inflate(-5, -5);
TextRenderer.DrawText(g, DateTime.Now.ToString("HH:mm:ss"), this.Font,
new Rectangle(r1.Left, r1.Top + 2 * r1.Height / 3, r1.Width, r1.Height / 3),
Color.Black);
e.Graphics.TranslateTransform(r2.Left + r2.Width / 2, r2.Top + r2.Height / 2);
var c = g.BeginContainer();
g.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.RotateTransform(DateTime.Now.Hour * 30f + DateTime.Now.Minute / 2f);
g.FillEllipse(Brushes.Black, -5, -5, 10, 10);
using (var p = new Pen(Color.Black, 4))
g.DrawLine(p, 0, 0, 0, -r2.Height / 2 + 30);
g.EndContainer(c);
c = g.BeginContainer();
g.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.RotateTransform(DateTime.Now.Minute * 6);
using (var p = new Pen(Color.Black, 2))
g.DrawLine(p, 0, 0, 0, -r2.Height / 2 + 10);
g.EndContainer(c);
c = g.BeginContainer();
g.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.RotateTransform(DateTime.Now.Second * 6);
using (var p = new Pen(Color.Red, 2))
g.DrawLine(p, 0, 10, 0, -r2.Height / 2 + 15);
g.EndContainer(c);
}
Then the result would be like this:
这篇关于模拟时钟 - 在时钟上绘制时钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!