将值从一个地方传递到另一个地方

3

这是我在任何语言中学习类的第一次尝试。我正在尝试创建一个Windows窗体项目,它是一个秒表。我创建了一个类,其中有一个StartClock方法来启动停表,然后将经过的时间放入一个TimeSpan变量中。然后,我将elapsedTime字符串设置为格式化字符串与TimeSpan变量相等。以下是代码。

 public class CStopWatch
{

     Stopwatch sw = new Stopwatch();

    private DateTime startTime;

    private DateTime stopTime;

    private String elapsedTime;

    public String ElapsedTime
    {
        get
        { 
            return elapsedTime; 
        }


    }

     public String StartClock()
     {

         sw.Start();
         TimeSpan ts = sw.Elapsed;
         elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
         return elapsedTime;


     }

    public void StopClock()
     {
        // sw.Stop();
     }

}

在Windows表单中,我调用了我的CStopwatch类的一个新实例,然后在开始按钮的点击事件中启动我的表单计时器,调用我的StartClock方法,然后将时间间隔设置为每秒钟。

在我的计时器Tick事件中,我将标签设置为显示经过的时间字符串变量。当我运行这个程序时,没有出现任何错误,但标签没有改变。下面是我的Windows表单代码。

 public partial class Form1 : Form
{
   // string elapsedTime;

   // public string elapsedTime { get { return elapsedTime; } }

    CStopWatch sw = new CStopWatch();

    public Form1()
    {
        InitializeComponent();
    }

    private void lblTime_Click(object sender, EventArgs e)
    {

    }


    private void btnStart_Click(object sender, EventArgs e)
    {
        timer.Enabled = true;
        sw.StartClock();
        timer.Interval = 1000;

        //Testing without using classes
        /*
        timer.Enabled = true;
        sw.Start();
        timer.Interval = 1000;
        TimeSpan ts = sw.Elapsed;
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
      */

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void timer_Tick(object sender, EventArgs e)
    {

        lblTime.Text = sw.ElapsedTime;


    }
}

我肯定我错过了什么或者做了一些愚蠢的事情,但是我的所有谷歌搜索都没有给我带来答案。提前致谢。


当您说标签没有变化时,它是否有任何值?还是它有一个初始值,但值没有得到更新? - d.moncada
我已将标签的文本属性设置为00:00:00。 - Lance Hietpas
6个回答

3

在点击“开始”按钮后,您只分配了变量elapsedTime的值一次。然后,在timer_Tick方法中尝试从它(使用ElapsedTime属性)读取值,但您没有分配新值。可以尝试以下内容:

public String ElapsedTime
    {
        get
        { 
            TimeSpan ts = sw.Elapsed;
            return String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
        }
    }

谢谢!我已经将我的类中的代码更改为以下内容,但似乎仍然没有更新。`public String ElapsedTime { get { TimeSpan ts = sw.Elapsed; return String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds / 10); } }public void StartClock() { sw.Start(); }` - Lance Hietpas
“timer_Tick”函数是否被调用了? :) 如果是,看看d.moncada的回答。这可能是另一个线程试图更新您的GUI引起的问题。请注意,只有GUI线程才能修改GUI组件。 - Valker
明白了!再次感谢! - Lance Hietpas

1
这是因为elapsedTime只被设置一次,然后就再也没有更新过。
public String ElapsedTime
{
    get
    { 
      return String.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed);
    }
}

这应该可以解决问题。因此,elapsedTime的声明和初始化是无用的,可以删除:
public class CStopWatch
{
    Stopwatch sw = new Stopwatch();

    public String ElapsedTime
    {
        get
        { 
            return String.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed);
        }            
    }

    public void StartClock()
    {
        sw.Start();
    }

    public void StopClock()
    {
        sw.Stop();
    }
}

1
我认为你的当前实现存在一些问题。更新你的WinForms代码后端,以便在设置Interval之后发生StartClock。此外,如果Timer在另一个线程上运行,你需要Invoke控件。最后,在每次Tick发生时,你需要更新ElapsedTime
public partial class Form1 : Form
{
    CStopWatch sw = new CStopWatch();

    public Form1()
    {
        InitializeComponent();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        timer.Interval = 1000;
        timer.Enabled = true;

        lblTime.Text = sw.StartClock();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void timer_Tick(object sender, EventArgs e)
    {
        UpdateElapsedTime();

       if (lblTime.InvokeRequired) 
       {
            lblTime.Invoke(new MethodInvoker(() => 
            { 
                lblTime.Text = sw.ElapsedTime;
            }));
       }
    }
}

然后,您可以更新CStopWatch类以包含一个名为UpdateElapsedTime的方法。
public class CStopWatch
{
    private Stopwatch sw = new Stopwatch();
    private DateTime startTime;
    private DateTime stopTime;
    private String elapsedTime;

    public String ElapsedTime
    {
        get
        { 
            return elapsedTime; 
        }
    }

    public String StartClock()
    {
        sw.Start();

        UpdateElapsedTime();

        return ElapsedTime;
    }

    public void UpdateElapsedTime()
    {
        TimeSpan ts = sw.Elapsed;
        ElapsedTime = String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds / 10); 
    }

    public void StopClock()
    {
        sw.Stop();
    }
}

0

看看this,我认为计时器的滴答事件发生在另一个线程上,这不允许更新UI,该链接显示了根据使用的.NET版本而有所不同的解决方案。


0

请尝试以下操作

timer.Elapsed += OnTimedEvent;
timer.Interval = 1000;
timer.Enabled = true;
sw.StartClock();

添加以下方法:
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        lblTime.Text = string.Format("{0:HH:mm:ss.fff}",e.SignalTime);
    }

0
问题在于您实际上没有更新您的elapsedTime变量。您可以改为在ElapsedTime属性中使用您的Stopwatch
public String ElapsedTime
{
    get
    {
        return string.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds / 10);
    }
}

或者等价地(C# 6.0):

public String ElapsedTime => $"{sw.Elapsed.Hours:00}:{sw.Elapsed.Minutes:00}:{sw.Elapsed.Seconds/10:00}";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接