图形计时器控件无法正常工作

时间:2014-07-08 10:29:27

标签: c# winforms graphics controls

这是我制作的自定义控件,图形计时器,然而,它无法正常工作。随着剩余时间的减少,馅饼被填充以表示减少的时间量,但是它随着意外的角度而减小(为了调试目的而输出到列表框)。如何让它正常工作?此外,我对制作自定义控件非常陌生(这是我的第一个)所以任何有关良好编码指南的指针,不做的事情等都会非常有用。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TestCustomControl
{
    class GraphicalTimer : Control
    {
        public Color Timer { get; set; }
        public Color TimerEmpty { get; set; }
        public Color BorderColor { get; set; }
        private Timer t;
        public int MaxTime { get; set; }
        private int timeElapsed = 0;
        public GraphicalTimer()
        {
            DoubleBuffered = true;

            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            BackColor = Color.Transparent;

            t = new Timer();
            t.Interval = 1000;
            t.Tick += t_Tick;
        }

        public void Start()
        {
            t.Start();
        }

        public void Stop()
        {
            t.Stop();
        }

        public void Reset()
        {
            timeElapsed = 0;
            Invalidate();
        }

        void t_Tick(object sender, EventArgs e)
        {
            timeElapsed += 1;
            if (timeElapsed == MaxTime)
            {
                t.Dispose();
            }
            Invalidate();
        }

        private float getAngleFromTime()
        {
            if (timeElapsed == 0)
            {
                return 0;
            }
            else
            {
                MainWindow.lb.Items.Add((360 / (MaxTime / timeElapsed)).ToString());
                return (360 / (MaxTime / timeElapsed));
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            Rectangle rc = ClientRectangle;

            g.FillEllipse(new SolidBrush(Timer), rc);
            g.FillPie(new SolidBrush(TimerEmpty), rc, -90, getAngleFromTime());
            g.DrawEllipse(new Pen(BorderColor, 4), rc);

            Font font = new Font("Arial", (float)rc.Height * 0.4f, FontStyle.Bold, GraphicsUnit.Pixel);
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            g.DrawString((MaxTime - timeElapsed).ToString("D2"), font, new SolidBrush(Color.Black), new RectangleF((rc.Width - rc.Width / 2) / 2, (rc.Height - rc.Height / 2) / 2, rc.Width * 0.7f, rc.Height * 0.7f));
        }
    }

    class MainWindow : Form
    {
        GraphicalTimer gt;
        Button startButton;
        Button stopButton;
        Button resetButton;
        public static ListBox lb;
        public MainWindow()
        {
            this.Text = "Test Application";
            gt = new GraphicalTimer();
            gt.MaxTime = 20;
            gt.BorderColor = Color.BurlyWood;
            gt.Timer = Color.Aqua;
            gt.TimerEmpty = Color.White;
            gt.Top = 10;
            gt.Left = 10;
            gt.Width = 50;
            gt.Height = 50;
            this.Controls.Add(gt);

            startButton = new Button();
            startButton.Top = 70;
            startButton.Left = 30;
            startButton.AutoSize = true;
            startButton.Text = "Start Timer";
            startButton.Click += startButton_Click;
            this.Controls.Add(startButton);

            stopButton = new Button();
            stopButton.Top = 70;
            stopButton.Left = startButton.Right + 10;
            stopButton.AutoSize = true;
            stopButton.Text = "Stop Timer";
            stopButton.Click += stopButton_Click;
            this.Controls.Add(stopButton);

            resetButton = new Button();
            resetButton.Top = 70;
            resetButton.Left = stopButton.Right + 10;
            resetButton.AutoSize = true;
            resetButton.Text = "Reset Timer";
            resetButton.Click += resetButton_Click;
            this.Controls.Add(resetButton);

            lb = new ListBox();
            lb.Top = resetButton.Bottom + 10;
            lb.Left = 10;
            lb.Width = this.ClientSize.Width - 20;
            lb.Height = this.ClientSize.Height - lb.Top - 10;
            this.Controls.Add(lb);
        }

        void resetButton_Click(object sender, EventArgs e)
        {
            gt.Reset();
        }

        void stopButton_Click(object sender, EventArgs e)
        {
            gt.Stop();
        }

        void startButton_Click(object sender, EventArgs e)
        {
            gt.Start();
        }
    }

    class StartClass
    {
        static void Main()
        {
            MainWindow form = new MainWindow();
            Application.EnableVisualStyles();
            Application.Run(form);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您正在使用整数来计算角度,并且可能导致相当多的抖动。

360 / (MaxTime / timeElapsed)将首先评估整数算术中的temp = MaxTime / timeElapsed,然后360 / temp也使用整数除法。

尝试使用浮点数进行计算,然后在需要时将最终结果转换为整数值。即使编写360 * timeElapsed / MaxTime也可能会减少伪影,因为您首先乘以360 * timeElapsed这是准确的(除非timeElapsed非常大)。

答案 1 :(得分:0)

计算AngleForTime的方法是错误的。只需用以下代码替换您的方法,它就可以完成您的工作。

private float getAngleFromTime()
        {
            if (timeElapsed == 0)
            {
                return 0;
            }
            else
            {
                MainWindow.lb.Items.Add((360*timeElapsed) / MaxTime ).ToString();
                return (360*timeElapsed) / MaxTime ;
            }
        }