I have a button, which I press and it starts a countdown.
But, if I press the same button again, the timer must reset and do another countdown (with another time defined by my program, but now this is irrelevant).
Is there any way I can do this reset inside the same button_click?
Maybe checking if the button was clicked again so I can reset the timer values?
I have this timer tick
private int milliSecondsLeft = 0;
private int t = 0;
private bool timeSet = false;
private void timer2_Tick(object sender, EventArgs e)
{
string timeOp = dataGridView1.Rows[t].Cells[5].Value + "";
t++;
DateTime timeConvert;
DateTime dateTime = DateTime.Now;
if (!timeSet)
{
DateTime.TryParse(timeOp, out timeConvert);
milliSecondsLeft = (int)timeConvert.TimeOfDay.TotalMilliseconds;
timeSet = true;
timeSetNxt = false;
}
milliSecondsLeft = milliSecondsLeft - 1000;
if (milliSecondsLeft > 0)
{
var span = new TimeSpan(0, 0, 0, 0, milliSecondsLeft);
lblLeft.Text = span.ToString(#"hh\:mm\:ss");
}
else
{
timer2.Stop();
}
}
and this button_click
each time I press my button it goes t++;, then it reads another time value on my datagrid. thats why it must reset
int t = 1;
private void btn2_Click(object sender, EventArgs e)
{
timer2.Start();
lblLeft.Text = dataGridView1.Rows[t].Cells[5].Value.ToString();
string value = dataGridView1.Rows[t].Cells[5].Value.ToString();
lblLeft.Text = value.ToString();
t++;
}
You could use the Tag property of the Button to set a flag for that logic you want to create.
on the button click event
if (btnExample.Tag==0)
{
btnExample.Tag=1;
//call startCountDown function
}
else
{
btnExample.Tag=0;
// call reset
}
Show your Timer Code. To get the Number of resets. Use code below.
int button_clicked = new int();
private void button1_Click(object sender, EventArgs e)
{
// How many times you have Reset
button_clicked++;
// Your Timer Code
}
Just start a new Timer with Every click. Also, dispose the last one.
You can use button_clicked to know if a timer has been started and hence dispose if the button_clicked > 0
I would check if the timer is enabled
if (!timer2.Enabled) StartTimer2();
else ResetTimer2();
Related
Am new to C# and i need your help on this, I want to display one character at a time in a textbox this is my code
private void timer1_Tick(object sender, EventArgs e)
{
int i = 0; //why does this don't increment when it ticks again?
string str = "Herman Lukindo";
textBox1.Text += str[i];
i++;
}
private void button1_Click(object sender, EventArgs e)
{
if(timer1.Enabled == false )
{
timer1.Enabled = true;
button1.Text = "Stop";
}
else if(timer1 .Enabled == true )
{
timer1.Enabled = false;
button1.Text = "Start";
}
}
why does this don't increment when it ticks again?
Because your variable i is local to your event. You need to define it at class level.
int i = 0; //at class level
private void timer1_Tick(object sender, EventArgs e)
{
string str = "Herman Lukindo";
textBox1.Text += str[i];
i++;
}
On exit of your event, variable i becomes out of scope and looses its value. On the next event it is considered a new local variable with the initialized value of 0.
Next, you should also look for cross threaded exception. Since your TextBox is not getting updated on the UI thread.
The issue with you code is that you are assigning i = 0 with every tick, so it will always be 0 everytime it is used. I would suggest using a class level variable for this.
However, using a variable at class level means you are going to need to reset to 0 at some point, probably each time you start the timer.
A further point is that you are going to want to validate the tick event to ensure you don't try to access an index that doesn't exist (IndexOutOfRangeException). For this I would recommend automatically stopping the timer once the last letter has been printed.
With all that in mind, here is my suggested code:
int i = 0;// Create i at class level to ensure the value is maintain between tick events.
private void timer1_Tick(object sender, EventArgs e)
{
string str = "Herman Lukindo";
// Check to see if we have reached the end of the string. If so, then stop the timer.
if(i >= str.Length)
{
StopTimer();
}
else
{
textBox1.Text += str[i];
i++;
}
}
private void button1_Click(object sender, EventArgs e)
{
// If timer is running then stop it.
if(timer1.Enabled)
{
StopTimer();
}
// Otherwise (timer not running) start it.
else
{
StartTimer();
}
}
void StartTimer()
{
i = 0;// Reset counter to 0 ready for next time.
textBox1.Text = "";// Reset the text box ready for next time.
timer1.Enabled = true;
button1.Text = "Stop";
}
void StopTimer()
{
timer1.Enabled = false;
button1.Text = "Start";
}
I have a Windows Forms App written in C#. The idea is, that it draws a chart for 10 numbers after clicking a button. This works fine. I click the button, and I get a nice chart. However I also want to include a sort of "auto refresh" mode, where the chart is refreshed every few seconds. This would be enabled via Checkbox. Here's my code:
private void chartButton_Click(object sender, EventArgs e) //draw a chart after the button is clicked
{
Random rdn1 = new Random();
int value;
foreach (var series in ekran.Series) //clear previous values
{
series.Points.Clear();
}
for (int i = 0; i < 10; i++) //draw a chart from ten new values
{
value = rdn1.Next(0, 10); //for testing purpouses the value will be a random number a random number
ekran.Series["seria1"].Points.AddXY(i, value);
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
while(checkBox1.Checked) //click the chartButton every one second, when the checkbox is checked
{
//rysuj.PerformClick();
chartButton.PerformClick();
Thread.Sleep(1000);
}
}
And now for my problem. When I check the Checkbox, I will not get a chart until it finishes every iteration of the while loop. Since it's an infinite loop, I will never get my chart. If I rewrite the code to make only five iterations when the Checkbox is checked, I only get the chart for the fifth one (and after five seconds, as to be expected).
So my question is: how can I force this to draw a chart every time the button is clicked via chartButton.PerformClick()? When I click the button manually, everything works fine, it's just when I try to do it automatically, I get my problem.
EDIT
First of all,thank you for the replies. However, I'm still experiencing the same problem when using a timer. This is how my code looks now:
namespace ChartTest
{
public partial class Form1 : Form
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 1000;
}
void timer_Tick(object sender, EventArgs e)
{
timer.Enabled = false;
chartButton.PerformClick();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
while (checkBox1.Checked)
{
timer.Enabled = true; // Enable the timer
timer.Start(); // Start the timer
}
}
private void chartButton_Click(object sender, EventArgs e) //draw a chart after the button is clicked
{
Random rdn1 = new Random();
int value;
ekran.Series.Clear();
var series2 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "Series2",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = false,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
this.ekran.Series.Add(series2);
for (int i = 0; i < 100; i++)
{
value = rdn1.Next(0, 10);
series2.Points.AddXY(i, value);
}
}
}
}
Sorry for being a total noob, but I have no idea, what am I doing wrong this time.
This is exactly what a Timer is for. Have the checkbox start/stop or enable/disable the timer, and handle the Timer.Tick event to redraw your chart. In your case, the event handler could simply call chartButton.PerformClick(), or insert whatever code the PerformClick() does.
ETA: If the chart refresh is not instant, you will probably want to push it off to a separate thread. If it's instant, there's not really any need to deal with the threading though.
I would go the route of using a thread with combination of checkbox's checkChange() event. Essentially this will allow your application to keep running while the update code will execute periodically. The refresh is determined by the sleep time, not your manual click or any other value.. Example below on how I to do this:
Thread refreshThread = null;
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (refreshThread == null) //No thread running, assume it starts this way
{
refreshThread = new Thread(chartRefresh);
refreshThread.Start();
}
else //Thread is running, must terminate
{
refreshThread.Abort();
refreshThread = null;
}
}
private void chartRefresh()
{
while (true)
{
//code to refresh chart
Thread.Sleep(10000);
}
}
I am using timer in form to send a command to a controller after every 3 seconds when user presses button. The timer should stop after user again presses same button. But in my case timer doesn't stop. I am using timer in the following way.
private void autoModeTempBtn_Click(object sender, EventArgs e)
{
System.Timers.Timer tempTimer = new System.Timers.Timer(3000);
tempTimer.SynchronizingObject = this;
tempTimer.AutoReset = true;
if (autoModeTempBtn.Text == "Get Temperature Auto Mode")
{
autoModeTempBtn.Text = "hello";
tempTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTemperatureEvent);
tempTimer.Enabled = true;
}
else /*user presses button second time */
{
tempTimer.Stop();
tempTimer.AutoReset = false;
tempTimer.Enabled = false;
autoModeTempBtn.Text = "Get Temperature Auto Mode";
}
}
private void OnTemperatureEvent(object source, System.Timers.ElapsedEventArgs e)
{
//do something
}
Where I am making mistake?
You are creating your timer new every time you click the button. Create the timer once and just Start/Stop it everytime you click. Also you should use the System.Windows.Forms.Timer instead of the System.Timers.Timer.
var _timer = new Timer() { Interval = 3000 };
private void autoModeTempBtn_Click(object sender, EventArgs e)
{
if (!validateSerialNumber())
return;
if (!_timer.Enabled)
{
_timer.Start();
autoModeTempBtn.Text = "hello";
}
else
{
_timer.Stop();
autoModeTempBtn.Text = "Get Temperature Auto Mode";
}
}
And add this code to your constructor:
_timer.Tick += OnTemperatureEvent;
Basically, I've got multiple button in my Form, and I want for it show a Stopwatch in the button.Text when the button is pressed. (Button is modified to be a toggle button.) and to stop and reset the timmer when the button is toggled off. Simple enough it seemed but because I have multiple buttons that could be pressed in any order, and I don't know anything about threading, this seems to be much more difficult that I presumed.
My origional intent was to have a function that constantly runs every second and interates a interager only if the button is pressed using this code:
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);
}
}
Problem is, I don't know threading so when I call the function, its stuck doing this and only this.
Either way, once this is called, all i do us call my update function that updates all the buttons including the button.Text which displays the time[0]; (array built around buttons)
Is their a better way of doing this that doesn't cause so much CPU use and/or simply works?
Thanks for all the help!
-John Ivey
Assuming you using checkbox with property Button = Appearence, in event handler for 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;
}
}
}
Change your Jogger function:
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();
}
You also need some simple class to store checkbox and current time:
class CheckboxCounter
{
public CheckBox CheckBox;
public int Time;
}
Then you can add any number of checkboxes and just set event CheckedChanged to CheckBoxCheckedChanged.
Try this out. After re-building or running, you should have the new "ButtonTimer" at the top of your ToolBox. Drop a couple on your Form, run it, and see what happens when you click them. Right click them to "Reset" them:
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() for simplicity put inside loop . . but it is advisable to start to lean threading . you will just learn how to start thread and how make cross thread safe call
Next simple will be to use backgroundworker . look this http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok here is thread solution also as you wanted . Tested too . as a stop variable i used Tag. But u can inherit button to make state button.it be more clear way . And below code will use one thread per button . So u should make it in one thread to make it better solution . You can modify this code to do all checkings inside one thread . For this you start thread once can make delegate for attaching dinamically count function for each button or you can pass buttons before . With one word there are more than one way to do it. Good luck
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;
}
}
I found timer code from a web site and used it in my application and it works fine if I use the timer code inside a button_click handler, but I need to use the timer when I call a method, so I did copy and paste the same code from the button_click into the method but the timer always gives me zero. How do I fix it?
The following is the timer code.
public partial class Form1 : Form
{
//Timer decleration
DateTime startTime, StopTime;
TimeSpan stoppedTime;
bool reset;
bool startVariabl = true;
// The rest of the code..
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (startVariable) startMethod();
//
//The rest of the code...
}
private void startMethod()
{
//Timer
tmDisplay.Enabled = true;
// Reset display to zero
reset = true;
lblElapsed.Text = "00:00.00.0";
// Start timer and get starting time
if (reset)
{
reset = false;
startTime = DateTime.Now;
stoppedTime = new TimeSpan(0);
}
else
{
stoppedTime += DateTime.Now - StopTime;
}
}
private void tmDisplay_Tick(object sender, EventArgs e)
{
DateTime currentTime;
//Determine Ellapsed Time
currentTime = DateTime.Now;
// Display Time
lblElapsed.Text = HMS(currentTime - startTime - stoppedTime);
}
private string HMS(TimeSpan tms)
{
//Format time as string; leaving off last six decimal places.
string s = tms.ToString();
return (s.Substring(0, s.Length - 6));
}
I am new C# learner.
as keyboardP suggested in a comment you should add this line:
tmDisplay.Tick += new EventHandler(tmDisplay_Tick);
usually Tick handler is set once (unless you need to switch it to other callback or nullify it for some reason) so I would add it in your Form constructor assuming that timer is already created then or after timer initialization if you do it in some method.