Multiple timer with different interval in C#.net - c#

I want different timer with different interval that i input.For example, if I input 4, 4 timer create and show time in 4 label, where 1st timer's time change in 1sec,2nd timer's time change in 2sec,3rd timer's time change in 3sec and 4tn timer's time change in 4sec.Here is my code,
string input = textBox2.Text;
int n = Convert.ToInt32(input);
for (i = 1; i <= n; i++)
{
Timer timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000) * (i);
timer.Enabled = true;
timer.Start();
Label label = new Label();
label.Name = "label"+i;
label.Location = new Point(100, 100 + i * 30);
label.TabIndex = i;
label.Visible = true;
this.Controls.Add(label);
}
private void timer_Tick(object sender, EventArgs e)
{
label.Text = DateTime.Now.ToString();
}
But i don't get any output.What can i do.I use windows application.

I don't see how the Timer's Tick event handler can access a dynamic label that's not in it's scope.
Try
Label label = new Label();
label.Name = "label"+i;
label.Location = new Point(100, 100 + i * 30);
label.TabIndex = i;
label.Visible = true;
Timer timer = new Timer();
timer.Tick += (s, e) => label.Text = DateTime.Now.ToString();
timer.Interval = (1000) * (i);
timer.Enabled = true;
timer.Start();
Another alternative is to have a Dictionary<Timer, Label> and add controls to this dictionary as they are created and in the timer's tick handler use the dictionary to retrieve its corresponding Label

The other way, than Bala R shown to you is keep reference of variable in a dictionary (dict) for timer and label pairs, and access in event handler by sender reference (Full source code, with 2 text boxes ans a button, 2nd textbox contains text "3"), hope it will help:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ProjectDocumentationWorkspace.UI
{
public partial class MainForm : Form
{
private Dictionary<Timer, Label> dict = new Dictionary<Timer, Label>();
public MainForm()
{
InitializeComponent();
}
private void CreateTimers()
{
string input = textBox2.Text;
int n = Convert.ToInt32(input);
for (int i = 1; i <= n; i++)
{
Timer timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000) * (i);
Label label = new Label();
label.Name = "label" + i;
label.Location = new Point(100, 100 + i * 30);
label.TabIndex = i;
label.Visible = true;
this.Controls.Add(label);
dict[timer] = label;
timer.Enabled = true;
timer.Start();
}
}
private void timer_Tick(object sender, EventArgs e)
{
Timer t = (Timer)sender;
DateTime current = DateTime.Now;
dict[t].Text = string.Format("{0:00}:{1:00}:{2:00}", current.Hour, current.Minute, current.Second);
}
private void button1_Click(object sender, EventArgs e)
{
CreateTimers();
}
}
}

Related

Why the timer is not showing the dots on the label as text each time less one?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Extract
{
public partial class LoadingLabel : Label
{
private int TimeToCount = 300;
private int Interval = 1000;
private System.Windows.Forms.Timer _timer;
private int counter = 0;
public LoadingLabel()
{
InitializeComponent();
this.Font = new Font("Arial", 14, FontStyle.Bold);
StartCountDownTimer(Interval, true);
}
public void StartCountDownTimer(int Interval, bool EnableTimer)
{
_timer = new System.Windows.Forms.Timer
{
Interval = Interval,
Enabled = false
};
_timer.Enabled = EnableTimer;
_timer.Tick += (sender, args) =>
{
if (counter == 0)
{
this.Text = ".";
Thread.Sleep(3);
counter++;
}
if(counter == 1)
{
this.Text = "..";
Thread.Sleep(3);
counter++;
}
if(counter == 2)
{
this.Text = "...";
Thread.Sleep(3);
counter = 0;
}
};
}
}
}
The interval is set to 1000 one second.
I want to use the interval so each second it will add another dot starting from one dot to three.
Then in the end when there are three dots start over again from one.
I tried for testing using a Thread.Sleep but it's not working it's showing only the last three dots and that's it.
In the _timer.Tick your ifs are running sequentially.
You could replace 2nd and 3rd ifs with else if or replace your code with the following:
if (counter == 3)
{
this.Text = "";
counter = 0;
}
this.Text += ".";
Thread.Sleep(3);
counter++;
Also you could eliminate the counter field since its value is always equal to the Text.Length.
Try a simple solution:
public Form1()
{
InitializeComponent();
Text = "";
timer = new System.Windows.Forms.Timer
{
Interval = 1000
};
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object? sender, EventArgs e)
{
if (Text.Contains("..."))
{
Text = "";
}
else
{
Text += ".";
}
}

how to create multiple countdown timers in c# windows application form?

I had created multiple timers using for loop and the timers are diplayed in the corresponding labels.If i click the button "n" times then "n" times ll be created.This code shows error in time countdown during runtime. Each timer is getting decremented by different intervals.How to resolve this problem?
public Dictionary<Timer, Label> dict = new Dictionary<Timer, Label>();
int n = 1;
int timesec = 10;
private void CreateTimers()
{
for (int i = 1; i <= n; i++)
{
Timer timer = new Timer();
timer = new System.Windows.Forms.Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000);//1 sec
Label label = new Label();
label.Name = "label" + i;
label.Location = new Point(0, 100 + i * 30);
label.TabIndex = i;
label.Visible = true;
this.Controls.Add(label);
dict[timer] = label;
timer.Enabled = true;
timer.Start();
}
private void button2_Click(object sender, EventArgs e)
{
//function call
CreateTimers();
n++;
}
private void timer_Tick(object sender, EventArgs e)
{
//timer countdown
Timer t = (Timer)sender;
timesec--;
if (timesec == 0)
t.Stop();
dict[t].Text = timesec.ToString();
}
A couple of issues. First and foremost, you have to eliminate that loop, since that creates more timers than you probably realize. Also, since you want each timer to be independent, you can't change the timesec value.
Try using the value of the label to show the count down, something like this:
private void CreateTimer() {
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += timer_Tick;
timer.Interval = (1000);//1 sec
Label label = new Label();
label.Name = "label" + n.ToString();
label.Text = timesec.ToString();
label.Location = new Point(0, 100 + n * 30);
label.Visible = true;
this.Controls.Add(label);
dict.Add(timer, label);
timer.Enabled = true;
timer.Start();
n++;
}
private void timer_Tick(object sender, EventArgs e) {
System.Windows.Forms.Timer t = (System.Windows.Forms.Timer)sender;
Label l = dict[t];
int labelTime = 0;
if (Int32.TryParse(l.Text, out labelTime)) {
labelTime -= 1;
}
l.Text = labelTime.ToString();
if (labelTime == 0) {
t.Stop();
}
}

C# panel move with collision

I am new to C# and Winforms and try to make a moving panel. It should move right until the end of my window and then back left. It should bounce from side to side. But the only thing happened after hours of trying is that it moves left and stops.
Using this form tools:
Timer = tmrMoveBox (interval: 50)
Panel = pnlBox
Label = lblXY (for showing the X and Y coordinates in the form)
Here are my first best try:
private void tmrMoveBox(object sender, EventArgs e)
{
if (pnlBox.Location.X <= 316)
{
for (int i = 0; i <= 316; i++)
{
pnlBox.Location = new Point(
pnlBox.Location.X + 2, pnlBox.Location.Y);
string BoxLocationToString = pnlBox.Location.ToString();
lblXY.Text = BoxLocationToString;
}
}
else if (pnlBox.Location.X >= 0)
{
for (int i = 0; i >= 316; i++)
{
pnlBox.Location = new Point(
pnlBox.Location.X - 2, pnlBox.Location.Y);
string BoxLocationToString = pnlBox.Location.ToString();
lblXY.Text = BoxLocationToString;
}
}
}
And the second best try:
private void tmrMoveBox(object sender, EventArgs e)
{
int runBox = 1;
if(runBox == 1)
{
while (pnlBox.Location.X <= 316)
{
pnlBox.Location = new Point(
pnlBox.Location.X + 2, pnlBox.Location.Y);
string BoxLocationString = pnlBox.Location.ToString();
lblXY.Text = BoxLocationString;
runBox = 0;
}
}
else
{
while(pnlBox.Location.X > 0)
{
pnlBox.Location = new Point(
pnlBox.Location.X - 2, pnlBox.Location.Y);
string BoxLocationString = pnlBox.Location.ToString();
lblXY.Text = BoxLocationString;
runBox = 1;
}
}
}
Tried to use a while loop too but then the panel just disappears.
I'm no expert and just set this moving panel as a goal for myself. Hope anyone can give me a tip.
EDIT:
Form1.Designer.cs
this.timer1.Interval = 50;
this.timer1.Tick += new System.EventHandler(this.tmrMoveBox);
this.timer1.Start();
this.timer1.Step = 2;
Depending on what you're using:
Windows Forms
WPF
Create a Timer and subscribe to the Tick event. Also, you should create new int property Step.
1. Windows Forms:
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
int Step;
Form1 ()
{
InitializeComponent()
....
t.Interval = 15000; // specify interval time as you want
t.Tick += new EventHandler(timer_Tick);
t.Start();
this.Step = 2;
}
And in ticks event handler put your logic, without while
void timer_Tick(object sender, EventArgs e)
{
if (pnlBox.Location.X >= 316)
{
Step = -2;
}
if (pnlBox.Location.X <= 0)
{
Step = 2;
}
pnlBox.Location = new Point(
pnlBox.Location.X + Step , pnlBox.Location.Y);
string BoxLocationString = pnlBox.Location.ToString();
lblXY.Text = BoxLocationString;
}
So your box will move on one step per one timer tick.
1. WPF:
As System.Windows.Forms.Timer is not available, you may use System.Windows.Threading.DispatcherTimer:
using System.Windows.Threading;
DispatcherTimer t = new DispatcherTimer();
t.Interval = new TimeSpan(0, 0, 15); // hours, minutes, seconds (there are more constructors)
t.Tick += Timer_Tick;
t.Start();
Here is the code I used:
int d= 10;
private void timer1_Tick(object sender, EventArgs e)
{
//Reverse the direction of move after a collision
if(panel1.Left==0 || panel1.Right==this.ClientRectangle.Width)
d = -d;
//Move panel, also prevent it from going beyond the borders event a point.
if(d>0)
panel1.Left = Math.Min(panel1.Left + d, this.ClientRectangle.Width - panel1.Width);
else
panel1.Left = Math.Max(panel1.Left + d, 0);
}
Note:
To check the collision you should check:
Collision with left: panel1.Left==0
Collision with right: panel1.Right==this.ClientRectangle.Width
You should not allow the panel goes beyond the borders even a point, so:
The maximum allowed value for your panel left is this.ClientRectangle.Width - panel1.Width
The minimum allowed value for your panel left is 0
Also It's better to use this.ClientRectangle.Width instead of using hard coded 316.

System.InvalidOperationException in C# WPF

I want to move a rectangle in WPF application using the following code. However, I am getting the following error:
System.InvalidOperationException: Cannot use a DependencyObject that belongs to a different thread
I looked at other problems in stackoverflow but nothing worked.
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
Timer timer;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new Timer(500);
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
this.rect.Dispatcher.Invoke(new Action(()=>
rect.RenderTransform = translateTransform1));
//this.can.UpdateLayout();
this.can.Dispatcher.Invoke(new Action(()=>
this.can.UpdateLayout()
));
}
I would suggest you to use DispatcherTimer than a normal timer.
Please see the below solution. enjoy.
Note: for DispatcherTimer you will need to add the assembly reference for System.Windows.Threading
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
private DispatcherTimer timer = null;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Tick += timer_Tick;
timer.Start();
timer.IsEnabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
Dispatcher.BeginInvoke(new Action<TranslateTransform>(delegate(TranslateTransform t1)
{
rect.RenderTransform = t1;
this.can.UpdateLayout();
}), System.Windows.Threading.DispatcherPriority.Render, translateTransform1);
}
}
You are constructing a TranslateTransform (which is a DependencyObject) outside the UI thread. Easy fix:
this.rect.Dispatcher.Invoke(new Action(
() =>
{
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
rect.RenderTransform = translateTransform1;
}));
Arguably a better fix: use a DispatcherTimer instead and get rid of all your Dispatcher.Invoke calls.

Unable to update Label in prompt box

I am working on the following code:
private Label textLabel;
public void ShowDialog()
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
textLabel = new Label() { Left = 50, Top=20, Text="txt"};
TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
}
I am calling the above method using another method and trying to update the textLabel field inside a loop like this
public void doIt()
{
ShowDialog();
for(int i=0;i<10;i++)
{
textLabel.TEXT = ""+i;
Threading.Thread.Sleep(1000);
}
}
That is the way we do in Java, but in C# it I could not update the label text in this way. What is wrong here and why can't I update the text?
So this is how I would do it, it is not a complete solution but I hope it will point you in the right direction:
Make the Prompt class that will derive from the Form. Add the controls to it (I did it manually but you could use the designer). Add the Timer which will be triggered on each second and which will change the label's text. When the counter hits 10 stop the timer.
public partial class Prompt : Form
{
Timer timer;
Label textLabel;
TextBox textBox;
Button confirmation;
int count = 0;
public Prompt()
{
InitializeComponent();
this.Load += Prompt_Load;
this.Width = 500;
this.Height = 150;
textLabel = new Label() { Left = 50, Top = 20, Text = "txt" };
textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
this.Controls.Add(confirmation);
this.Controls.Add(textLabel);
this.Controls.Add(textBox);
timer = new Timer();
timer.Interval = 1000;
timer.Tick += timer_Tick;
}
void Prompt_Load(object sender, EventArgs e)
{
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
this.textLabel.Text = " " + count.ToString();
count++;
if (count == 10)
timer.Stop();
}
}
In the doIt method, create the instance of your Prompt form, set its caption and call its ShowDialog() method.
public void doIt()
{
Prompt p = new Prompt();
p.Text = caption;
p.ShowDialog();
}

Categories

Resources