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;
Related
I want to do frame animation and not sure should i use AnimationDrawable class for animation.
How do frame animation in Xamarin forms for Android. Is there any other approach? Simple example would be perfect.
I did trick just hiding and unhiding required elements. You could call from DoAnimation from any button click or smth else.
private void DoAnimation()
{
_timer = new System.Timers.Timer();
//Trigger event every second
_timer.Interval = 1000;
_timer.Elapsed += CheckStatus;
//count down 5 seconds
_countSeconds = 5000;
_timer.Enabled = true;
}
private void SpinAnimation()
{
switch (_letterShowState) {
case SomeStateStates.State1:
_pic1.IsVisible = false;
_pic2.IsVisible = true;
_pic3.IsVisible = false;
_letterShowState = SomeStateStates.State2;
break;
}
}
private void CheckStatus(object sender, System.Timers.ElapsedEventArgs e) {
_countSeconds--;
new System.Threading.Thread(new System.Threading.ThreadStart(() => {
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => {
SpinAnimation();
});
})).Start();
if (_countSeconds == 0)
{
_timer.Stop();
}
}
I used this link in order to solve my problem, but with a partial success
Change button color for a short time
I need to Present a red button.
Whenever the button is clicked, it changes its color to green for a period of 5 second,
Consecutive clicks should be supported but should not accumulate i.e. the button color should turn back to red 5 second after the last click.
my code:
private void myButton_Click(object sender, RoutedEventArgs e)
{
Timer timer = new Timer { Interval = 5000 };
timer.Elapsed += HandleTimerTick;
myButton.Background = new SolidColorBrush(Colors.LightGreen);
timer.Start();
}
private void HandleTimerTick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
myButton.Dispatcher.BeginInvoke((Action)delegate()
{
myButton.Background = new SolidColorBrush(Colors.Red);
});
}
it works but just 5 seconds from my first click and the timer not resets every time I've click the button.
Thanks for your help.
You have to move the timer out of the event and restart it every time the user clicks. Something along these lines:
public partial class MainWindow : Window
{
private Timer timer;
public MainWindow()
{
InitializeComponent();
timer = new Timer{Interval = 5000};
}
private void Button_Click(object sender, RoutedEventArgs e)
{
timer.Elapsed += HandleTimerTick;
myButton.Background = new SolidColorBrush(Colors.LightGreen);
timer.Stop();
timer.Start();
}
private void HandleTimerTick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
myButton.Dispatcher.BeginInvoke((Action)delegate()
{
myButton.Background = new SolidColorBrush(Colors.Red);
});
}
}
How can I change the text of button with timeout? I tried out with the following code but it is not working.
private void button1_Click(object sender, EventArgs e)
{
Stopwatch sw = new Stopwatch();
sw.Start();
if (button1.Text == "Start")
{
//do something
button1.Text = "stop"
if (sw.ElapsedMilliseconds > 5000)
{
button1.Text = "Start";
}
}
How can I correct my code?
You need to use Timer instead:
Timer t = new Timer(5000); // Set up the timer to trigger on 5 seconds
t.SynchronizingObject = this; // Set the timer event to run on the same thread as the current class, i.e. the UI
t.AutoReset = false; // Only execute the event once
t.Elapsed += new ElapsedEventHandler(t_Elapsed); // Add an event handler to the timer
t.Enabled = true; // Starts the timer
// Once 5 seconds has elapsed, your method will be called
void t_Elapsed(object sender, ElapsedEventArgs e)
{
// The Timer class automatically runs this on the UI thread
button1.Text = "Start";
}
Stopwatch is only for measuring how much time has passed since you called Start().
If you're using C# 5
private async void button1_Click(object sender, EventArgs e)
{
button1.Text = "Stop";
await Task.Delay(5000);
button1.Text = "Start";
}
You could use a timer. In this example the text of the button changes to "Stop" after 5 seconds.
private Timer timer = new Timer();
private void button1_Click(object sender, EventArgs e)
{
timer.Interval = 5000; // interval length
timer.Tick += TimerOnTick;
timer.Enabled = true; // activate timer
button1.Text = "Start";
}
private void TimerOnTick(object sender, EventArgs eventArgs)
{
timer.Enabled = false; // deactivate timer
button1.Text = "Stop";
}
I think you can reach your goal by using Timer
Example of using Timer
public partial class FormWithTimer : Form
{
Timer timer = new Timer();
public FormWithTimer()
{
InitializeComponent();
// Everytime timer ticks, timer_Tick will be called
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000) * (1); // Timer will tick every second
timer.Enabled = true; // Enable the timer
}
// .......
showForm() // declaration
{
timer.start();
// .......
timer.stop();
}
void timer_Tick(object sender, EventArgs e)
{
//hide form...through visibility
}
}
Use this instead of Stopwatch:
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "stop"
aTimer = new System.Timers.Timer(5000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
button1.Text = "Start";
var atim = source as Timer;
if (atim != null)
atim.Elapsed -= OnTimedEvent;
}
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 would like to set a textbox text to "blink" by changing text colors when a button is clicked.
I can get the text to blink how I want it to, but I want it to stop after a few blinks. I cannot figure out how to make it stop after the timer fires a few times.
Here is my code:
public Form1()
{
InitializeComponent();
Timer timer = new Timer();
timer.Interval = 500;
timer.Enabled = false;
timer.Start();
timer.Tick += new EventHandler(timer_Tick);
if (timerint == 5)
timer.Stop();
}
private void timer_Tick(object sender, EventArgs e)
{
timerint += 1;
if (textBoxInvFooter.ForeColor == SystemColors.GrayText)
textBoxInvFooter.ForeColor = SystemColors.Highlight;
else
textBoxInvFooter.ForeColor = SystemColors.GrayText;
}
I know my problem lies with how I'm using the "timerint", but I'm not sure where to put it, or what solution I should use...
Thank you for all your help!
You just have to put the timer check inside the Tick handler. You can access the Timer object by using the sender argument of the handler.
private void timer_Tick(object sender, EventArgs e)
{
// ...
timerint += 1;
if (timerint == 5)
{
((Timer)sender).Stop();
}
}
Here's the complete code that I would use to solve your issue. It correctly stops the timer, detaches the event handler, and disposes the timer. It disables the button during the flashing, and also restores the colour of the textbox after the five flashes are complete.
The best part is that it is purely defined within the one lambda, so no class-level variables required.
Here it is:
button1.Click += (s, e) =>
{
button1.Enabled = false;
var counter = 0;
var timer = new Timer()
{
Interval = 500,
Enabled = false
};
EventHandler handler = null;
handler = (s2, e2) =>
{
if (++counter >= 5)
{
timer.Stop();
timer.Tick -= handler;
timer.Dispose();
textBoxInvFooter.ForeColor = SystemColors.WindowText;
button1.Enabled = true;
}
else
{
textBoxInvFooter.ForeColor =
textBoxInvFooter.ForeColor == SystemColors.GrayText
? SystemColors.Highlight
: SystemColors.GrayText;
}
};
timer.Tick += handler;
timer.Start();
};