模拟时钟 - 在时钟上绘制时钟 [英] Analog Clock - Draw clocks arm over a Label

查看:279
本文介绍了模拟时钟 - 在时钟上绘制时钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆