倒数计时器变为负数 (00:00:00)

Posted

技术标签:

【中文标题】倒数计时器变为负数 (00:00:00)【英文标题】:Countdown timer goes into negative number (00:00:00) 【发布时间】:2015-08-24 13:01:48 【问题描述】:

我做了一个简单的倒数计时器,但是当我在文本框中输入0 : 0 : 0 时,计时器变为负数-1 : 59 : 59。我尝试输入0 : 0 : 1,计时器停在0 : 0 : 0,消息框出现在屏幕上

我试过这段代码来防止负值,但它停在-1 : 59 : 58

if (label1.Text == "-1")

    timer1.Stop()

试过这段代码,但它停在-1 : 59 : 59

if (h < 0)

    timer1.Stop();

这里是代码

namespace Timer


    public partial class Form1 : Form
    

        int h;
        int m;
        int s;
        public Form1()
        
            InitializeComponent();
        

        private void button1_Click(object sender, EventArgs e)
        
            if (textBox1.Text == "")
            
                textBox1.Text = "0";
            
            if (textBox2.Text == "")
            
                textBox2.Text = "0";
            
            if (textBox3.Text == "")
            
                textBox3.Text = "0";
            

            h = Convert.ToInt32(textBox1.Text);
            m = Convert.ToInt32(textBox2.Text);
            s = Convert.ToInt32(textBox3.Text);

            timer1.Start();
        

        private void timer1_Tick(object sender, EventArgs e)
        
            s = s - 1;

            if(s == -1)
            
                m = m - 1;
                s = 59;
            

            if (m == -1)
            
                h = h - 1;
                m = 59;
            
            if (h == 0 && m == 0 && s == 0)
            
                timer1.Stop();
                MessageBox.Show("Times up!", "Time");
            

            string hh = Convert.ToString(h);
            string mm = Convert.ToString(m);
            string ss = Convert.ToString(s);

            label1.Text = hh;
            label2.Text = mm;
            label3.Text = ss;
        

        private void button2_Click(object sender, EventArgs e)
        
            timer1.Stop();
        
    

【问题讨论】:

您是否尝试使用调试器查看发生了什么 您是否已通过代码查看发生了什么?代码完全按照您的要求执行 - 逐步执行并观察,您会看到。 线索 - 错误在刻度处理程序的第一行 你为什么不使用 TimeSpan 对象? 【参考方案1】:

您没有涵盖提供 0:0:0 的情况。 替换这个:

        s = s - 1;

        if(s == -1)
        
            m = m - 1;
            s = 59;
        

        if (m == -1)
        
            h = h - 1;
            m = 59;
        

用这个:

if(s > 0 || m > 0 || h > 0)

            s = s - 1;
            if(s == -1)
            
                m = m - 1;
                s = 59;
            

            if (m == -1)
            
                h = h - 1;
                m = 59;
            

【讨论】:

【参考方案2】:

您的代码正在按照您的要求执行,问题是您没有处理从0:0:0 开始的极端情况

我认为这将被视为无效输入,因此处理此问题的最简单方法可能是在单击按钮启动计时器之前进行检查:

        h = Convert.ToInt32(textBox1.Text);
        m = Convert.ToInt32(textBox2.Text);
        s = Convert.ToInt32(textBox3.Text);

        // one of these must be non-zero
        if (h != 0 || m != 0 || s != 0)
        
            timer1.Start();
        
        else
        
            // handle this how ever you want but you don't need to start a timer
            // and really shouldn't start the timer
        

如果用户输入全零,让计时器计时实际上是错误的,因为当他们要求 0 秒时,他们会得到 1 秒。

更好的做法是在输入非零时间之前实际禁用按钮。为此,我建议将TextBox 替换为NumericUpDown(因为无论如何只有数字输入有效),然后为其ValueChanged 事件添加处理程序。在该处理程序中,检查三个控件中的任何一个都具有非零值,如果有,则启用该按钮。如果它们都为零,请禁用该按钮。

这里有一个重要的问题 - System.Windows.Forms.Timer 并不是特别准确,因此不要期望设置为每 1 秒滴答一次的计时器实际上是每秒钟滴答一次。每次滴答之间至少 1 秒,但通常会多出几毫秒。所以你的倒计时会漂移。如果您将其设置为倒计时 1 分钟(即60 秒),如果它实际上需要62 秒倒计时,请不要感到惊讶。如果这对您很重要,那么您应该在启动计时器时记录当前时间,然后检查当前时间与启动计时器的时间之间的差异,并使用它来更新您的标签。

更好的整体解决方案可能如下所示:

DateTime end;

private void button1_Click(object sender, EventArgs e)

    var h = hourNumericUpDown.Value;
    var m = minuteNumericUpDown.Value;
    var s = secondsNumericUpDown.Value;
    if (h != 0 || m != 0 || s != 0)
    
        var start = DateTime.Now;
        var timeSpan = new TimeSpan(0,h,m,s);
        end = start.Add(timeSpan);
        countDownLabel.Text = timeSpan.ToString();  
        timer1.Start();
    


private void timer1_Tick(object sender, EventArgs e)

    var timeleft = end - DateTime.Now;
    if (timeLeft.Ticks < 0) 
    
        countDownLabel.Text = "00:00:00";
        timer1.Stop();
        MessageBox.Show("Times up!", "Time");
    
    else 
    
        countDownLabel.Text = string.Format("0:D2:1:D2:2:D2", 
            timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds);
    

然后你可能最好将计时器设置得更快。也许每半秒,或每四分之一秒,这样显示器的关闭时间就不会超过那个。

【讨论】:

感谢您的信息。此代码有效,但计时器正在倒计时,如 5:59:59.2029422 @JohnWilliam:啊,那么就格式化吧,比如:countDownLabel.Text = string.Format("0:D2:1:D2:2:D2", timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds);【参考方案3】:

当 h 变为负数时,您没有检查,我添加了一个,您可以添加您的。

 if (s == -1)
        
            m = m - 1;
            s = 59;
        

        if (m == -1)
        
            h = h - 1;
            m = 59;
        
        /*I added such condition*/
        if(h < 0)
        
            h = 0;
            m = 0;
            s = 0;
        
        if (h == 0 && m == 0 && s == 0)
        
            timer1.Stop();
            MessageBox.Show("Times up!", "Time");
            return;//return early
        

【讨论】:

以上是关于倒数计时器变为负数 (00:00:00)的主要内容,如果未能解决你的问题,请参考以下文章

按秒倒数计时器

动态 Python 倒数计时器

为啥倒数计时器突然执行得很快?

带有 CircularProgressIndicator 的倒数计时器

如何检查可观察倒数计时器是不是已完成?

Flutter:当倒数计时器达到 0 时执行动作