c#中的秒表更改按钮文本
本文关键字:按钮 文本 | 更新日期: 2023-09-27 18:14:35
基本上,我在我的表单中有多个按钮,我想在按钮中显示一个秒表。按下按钮时的文本。(按钮被修改为切换按钮)以及当按钮被关闭时停止和重置定时器。这看起来很简单,但因为我有多个按钮,可以按任何顺序,我不知道线程,这似乎比我想象的要困难得多。
我最初的意图是有一个函数,持续运行每秒钟,只有当按钮被按下使用以下代码的interager:
public void Jogger()//purpose is to step up time[0] every second only when a button is on.
{
while (true)
{
for (int i = 0; i < 16; i++)
{
if (btnstat[i])
time[i]++;
}
Thread.Sleep(1000);
}
}
问题是,我不知道线程,所以当我调用这个函数时,它被卡住了,只有这个。
不管怎样,一旦这个被调用,我所做的就是调用我的update函数来更新所有的按钮,包括按钮。显示时间[0]的文本;(数组围绕按钮构建)
是否有一种更好的方法来做到这一点,不会导致太多的CPU使用和/或简单地工作?
谢谢你的帮助!镜头转艾维
假设您使用带有属性Button = appearance的复选框,在CheckedChanged事件处理程序中:
private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox checkBox = (CheckBox) sender;
if (checkBox.Checked)
{
Timer timer = new Timer {Interval = 1000};
timer.Tick += Jogger;
timer.Start();
timer.Tag = new CheckboxCounter {CheckBox = checkBox, Time = 0};
checkBox.Tag = timer;
}
else
{
Timer timer = checkBox.Tag as Timer;
if (timer != null)
{
timer.Tag = null;
timer.Stop();
timer.Dispose();
checkBox.Tag = null;
}
}
}
更改慢跑者功能:
private void Jogger(object a_sender, EventArgs a_eventArgs)
{
Timer timer = (Timer) a_sender;
CheckboxCounter data = (CheckboxCounter)timer.Tag;
data.Time++;
data.CheckBox.Text = data.Time.ToString();
}
您还需要一些简单的类来存储复选框和当前时间:
class CheckboxCounter
{
public CheckBox CheckBox;
public int Time;
}
然后你可以添加任意数量的复选框,只需将事件CheckedChanged设置为CheckBoxCheckedChanged。
试试这个。重新构建或运行后,您应该在工具箱的顶部有一个新的"ButtonTimer"。在窗体上放置一对,运行它,看看单击它们时会发生什么。右击它们"重置"它们:
public class ButtonTimer : CheckBox
{
private System.Windows.Forms.Timer Tmr = new System.Windows.Forms.Timer();
private System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
public ButtonTimer()
{
this.Tmr.Interval = 500;
this.Tmr.Tick += new EventHandler(tmr_Tick);
this.Appearance = System.Windows.Forms.Appearance.Button;
this.CheckedChanged += new EventHandler(ButtonTimer_CheckedChanged);
ContextMenuStrip cms = new ContextMenuStrip();
ToolStripItem tsi = cms.Items.Add("Reset");
tsi.Click += new EventHandler(tsi_Click);
this.ContextMenuStrip = cms;
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
this.Text = TimeSpan.Zero.ToString(@"hh':mm':ss");
}
private void ButtonTimer_CheckedChanged(object sender, EventArgs e)
{
if (this.Checked)
{
this.SW.Start();
this.Tmr.Start();
}
else
{
this.SW.Stop();
this.Tmr.Stop();
}
}
private void tmr_Tick(object sender, EventArgs e)
{
this.UpdateTime();
}
private void UpdateTime()
{
this.Text = this.SW.Elapsed.ToString(@"hh':mm':ss");
}
private void tsi_Click(object sender, EventArgs e)
{
if (this.SW.IsRunning)
{
SW.Restart();
}
else
{
SW.Reset();
}
this.UpdateTime();
}
}
Application.DoEvents()
放入循环中。但建议从学习threading
开始。您将学习如何启动线程以及如何进行跨线程安全调用下一个简单的将是使用backgroundworker
。看这个http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok,这里是线程解决方案也如您所愿。也测试过了。我使用Tag作为停止变量。但是你可以继承button来创建state button。这是更明确的方式。下面的代码将为每个按钮使用一个线程。所以你应该让它在一个线程,使它更好的解决方案。您可以修改这段代码,使其在一个线程内完成所有检查。为此,你可以启动线程一次,可以为每个按钮绑定动态计数函数委托,或者你可以传递按钮之前。一个词有不止一种表达方式。祝你好运
this.button1.Click += new System.EventHandler(this.button_Click);
this.button2.Click += new System.EventHandler(this.button_Click);
...and so on
private void button_Click(object sender, EventArgs e)
{
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private void button_Click(object sender, EventArgs e)
{
Button mybtn=sender as Button;
if((string)mybtn.Tag=="start"){
mybtn.Tag ="";
return;
}
mybtn.Tag = "start";
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private bool setResult(object obj,string text)
{
if (this.textBox1.InvokeRequired)
{
Func<Button,string, bool > d = new Func<Button,string,bool >(setResult);
return (bool)this.Invoke(d,obj,text);
}
else
{
Button btn=obj as Button;
if (btn != null)
{
btn.Text = text;
if ((string)btn.Tag !="start") return false;
}
return true;
}
}
private void Jogger2(object mybtn)
{
int ii = 0;
while (true)
{
Thread.Sleep(1000);
//replace with your code
ii += 1;
if (!setResult(mybtn, ii.ToString())) break;
}
}