制作简单准确秒表的最佳方法

The best way to make a simple and accurate stopwatch

我有一个项目,我必须做一个秒表。它可以工作,但与 Windows 计时器相比并不准确。另外,我想知道是否有另一种有效且简单的方法可以做到这一点,如果有,我该怎么做?。 Timer的间隔为1.

这是我的代码:

    Dim min As Integer = 30
    Dim seg As Integer = 59
    Dim mseg As Integer = 99
    Private Sub tmTimer_Tick(sender As Object, e As EventArgs) Handles tmTimer.Tick

        If lblStopWatch.Text = "00:00:00" Then
            lblStopWatch.ForeColor = Color.DarkGray
            tmTimer.Enabled = False
            min = 30
            seg = 59
            mseg = 99
        Else
            mseg -= 1
            If mseg < 0 Then
                mseg = 99
                seg -= 1
                If seg < 0 Then
                    seg = 59
                    min -= 1
                End If
            End If

            If min < 10 And seg < 10 And mseg < 10 Then
                lblStopWatch.Text = "0" + min.ToString + ":0" + seg.ToString + ":0" + mseg.ToString
            ElseIf min < 10 And seg < 10 Then
                lblStopWatch.Text = "0" + min.ToString + ":0" + seg.ToString + ":" + mseg.ToString
            ElseIf min < 10 And mseg < 10 Then
                lblStopWatch.Text = "0" + min.ToString + ":" + seg.ToString + ":0" + mseg.ToString
            ElseIf seg < 10 And mseg < 10 Then
                lblStopWatch.Text = min.ToString + ":0" + seg.ToString + ":0" + mseg.ToString
            Else
                If mseg < 10 Then
                    lblStopWatch.Text = min.ToString + ":" + seg.ToString + ":0" + mseg.ToString
                ElseIf seg < 10 Then
                    lblStopWatch.Text = min.ToString + ":0" + seg.ToString + ":" + mseg.ToString
                ElseIf min < 10 Then
                    lblStopWatch.Text = "0" + min.ToString + ":" + seg.ToString + ":" + mseg.ToString
                Else
                    lblStopWatch.Text = min.ToString + ":" + seg.ToString + ":" + mseg.ToString
                End If
            End If
        End If
    End Sub

这是可以启动计时器的按钮:

Private Sub btnAcept_Click(sender As Object, e As EventArgs) Handles btnAcept.Click

     lblCronometro.ForeColor = Color.RoyalBlue
        lblCronometro.Text = "30:00:00"
        tmCronometro.Enabled = True
        tmCronometro.Start()

End Sub

如果示例是用 C# 或 vb,我可以同时获得。 谢谢

.NET Framework 包含 Stopwatch class,因此您应该使用它。它非常准确,至少在您的代码按时执行其方法的程度上是这样。它有 StartStopRestartReset 的方法,它提供了作为 TimeSpan 的经过时间,您可以直接格式化而不是所有的连接.使用 Timer 的唯一目的是允许您在 Label 中显示当前经过的时间。例如

Private ReadOnly stopwatch As New Stopwatch

Private Sub startButton_Click(sender As Object, e As EventArgs) Handles startButton.Click
    DisplayElapsedTime()

    stopwatch.Start()
    displayTimer.Start()

    startButton.Enabled = False
    stopButton.Enabled = True
    restartButton.Enabled = True
    resetButton.Enabled = False
End Sub

Private Sub stopButton_Click(sender As Object, e As EventArgs) Handles stopButton.Click
    stopwatch.Stop()
    displayTimer.Stop()

    DisplayElapsedTime()

    startButton.Enabled = True
    stopButton.Enabled = False
    restartButton.Enabled = False
    resetButton.Enabled = True
End Sub

Private Sub restartButton_Click(sender As Object, e As EventArgs) Handles restartButton.Click
    stopwatch.Restart()

    DisplayElapsedTime()
End Sub

Private Sub resetButton_Click(sender As Object, e As EventArgs) Handles resetButton.Click
    stopwatch.Reset()

    DisplayElapsedTime()
End Sub

Private Sub displayTimer_Tick(sender As Object, e As EventArgs) Handles displayTimer.Tick
    DisplayElapsedTime()
End Sub

Private Sub DisplayElapsedTime()
    elapsedTimeLabel.Text = stopwatch.Elapsed.ToString("m\:ss\.fff")
End Sub

提示

如果您想自己做而不是使用现有的 StopWatch class,另一种选择是跟踪秒表开始的时间 (start) 和秒表有多长时间 运行 (elapsed).

有了 start 值,我们可以计算计时器的 Tick 事件中的 elapsed 时间,例如:

// elapsed is a TimeSpan object
elapsed = DateTime.Now - start;

如果我们添加停止秒表然后再次启动它的功能(无需重置),那么我们必须考虑 "downtime"。我们可以通过从当前时间减去 elapsed 时间并使用 that 值作为开始时间来在 Start 按钮单击事件中执行此操作:

// start is a DateTime object
start = DateTime.Now.Subtract(elapsed);

然后,当我们想向用户显示经过的时间时,我们可以只使用我们的 elapsed 字段并将其格式化为:hours:minutes:seconds.milliseconds 使用自定义格式字符串。

// I noticed you're doing a countdown timer, so we want to display the difference
// between the original duration of 30 minutes and the elapsed time we've been running
lblStopwatch.Text = (duration - elapsed).ToString("hh\:mm\:ss\.ff");

回答

如果这些提示还不够,这里有一个使用该策略的示例项目:

public partial class Form1 : Form
{
    private DateTime _startTime;
    private TimeSpan _elapsedTime;

    // The starting duration for the countdown timer
    private readonly TimeSpan _duration = TimeSpan.FromMinutes(30);

    public Form1()
    {
        InitializeComponent();
        ResetTimer();
    }

    private void ResetTimer()
    {
        _startTime = DateTime.Now;
        _elapsedTime = TimeSpan.Zero;
        UpdateStopwatchDisplay();
    }

    private void UpdateStopwatchDisplay()
    {
        // Display the current duration to the user
        lblStopwatch.ForeColor = timer1.Enabled ? Color.RoyalBlue : Color.DarkGray;
        lblStopwatch.Text = (_duration - _elapsedTime).ToString("hh\:mm\:ss\.ff");
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        // Subtract 'elapsed' from 'now' to account for any stoppage time
        _startTime = DateTime.Now.Subtract(_elapsedTime);
        UpdateStopwatchDisplay();
        timer1.Start();
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        timer1.Stop();
        UpdateStopwatchDisplay();
    }

    private void btnReset_Click(object sender, EventArgs e)
    {
        ResetTimer();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        // Update elapsed time
        _elapsedTime = DateTime.Now.Subtract(_startTime);

        // Stop the timer if we've reached our duration
        if (_elapsedTime >= _duration)
        {
            _elapsedTime = _duration;
            timer1.Stop();
        }

        UpdateStopwatchDisplay();
    }
}