How do I randomly generate integer values in a text box for every one second till I click on a button.
I came up with following code (Clicking on Button 1 should generate random integers for every 1 second in textBox1 till Button2 is clicked) and its not working (Output is empty text box).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
bool buttonclicked = false;
System.Timers.Timer myTimer;
System.Random r = new System.Random();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
while (buttonclicked == false)
{
myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(rnd);
myTimer.Interval = 1000;
myTimer.Start();
}
}
public void rnd(Object sender, EventArgs e)
{
textBox1.Text = r.Next(0, 1000).ToString();
}
private void button2_Click(object sender, EventArgs e)
{
buttonclicked = true;
myTimer.Stop();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
Your while(buttonclicked == false) will create an infinite loop once you click the button.You can just do
private void button1_Click_1(object sender, EventArgs e)
{
myTimer = new System.Timers.Timer();
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(rnd);
myTimer.Interval = 1000;
myTimer.Start();
}
private void button2_Click_1(object sender, EventArgs e)
{
myTimer.Stop();
}
and you need to make a safe thread call to the textbox by doing :
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
And to set the text just use SetText(r.Next(0 ,1000).ToString());
Looks like it is because you are using a while loop instead of an if block. Your condition should look like this:
if( buttonclicked == false)
{
....
}
I think you were right to a loop - but not the timer.
No need to declare the System.Random at the class level either - unless you're using it elsewhere.
Using a for loop.
private void button1_Click_1(object sender, EventArgs e)
{
var r = new System.Random();
for (var i = 0; i < 1000; i++)
{
textBox1.Text = r.Next(0, 1000).ToString();
}
}
Using a while loop.
private void button1_Click_1(object sender, EventArgs e)
{
var r = new System.Random();
var i = 0;
while (i < 1000)
{
textBox1.Text = r.Next(0, 1000).ToString();
i++;
}
}
If you really want to add a new number each second, you could use async and await (to stop UI blocking) and add a System.Threading.Thread.Sleep(1000);.
Or even Task based would be better than a Timer (in my opinion). It's good to understand how Tasks work.
A Timer is okay for this scenario - but in real applications they can get messy, especially with multiple timers.
Here is an example of how the above would work using Tasks.
private void button1_Click(object sender, EventArgs e)
{
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => AddRandomNumbers(uiScheduler));
}
private async Task AddRandomNumbers(TaskScheduler uiScheduler)
{
var r = new Random();
for (int i = 0; i < 1000; i++)
{
await Task.Factory.StartNew(
() => textBox1.Text = r.Next(0, 1000).ToString(),
CancellationToken.None,
TaskCreationOptions.None,
uiScheduler);
Thread.Sleep(1000);
}
}
Related
Here I have a chart (graph1) that normally should add a random point every 1second. but it doesn't... I tried to find out what the problem is but here I don't have anymore ideas...
The timer is started, label1 change every seconds but the chart doesn't change... with button one when I click it adds a new point.
what did I miss? please help... thanks a lot.
namespace Test_Chart1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 40;
System.Timers.Timer _Timer1s = new System.Timers.Timer(1000); //object
_Timer1s.Elapsed += _Timer1sElapsed; //event in object
_Timer1s.Start(); //start counting
}
private void _Timer1sElapsed(object sender, EventArgs e)//Timer each 100ms
{
if (label1.BackColor == Color.Red)
{
label1.BackColor = Color.Blue;
PutValueInGraph1();
}
else label1.BackColor = Color.Red;
}
private void button1_Click(object sender, EventArgs e)
{
PutValueInGraph1();
}
private void PutValueInGraph1()
{
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 100;
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum-10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
}
}
ok here is the new one:
public partial class Form1 : Form
{
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 1;
}
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum - 10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
private void btn_Start_Click_1(object sender, EventArgs e)
{
graph1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
graph1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
graph1.ChartAreas[0].AxisX.ScaleView.Size = 100;
myTimer.Start();
BlinkLed.BackColor = Color.YellowGreen;
}
private void btn_Stop_Click(object sender, EventArgs e)
{
myTimer.Stop();
BlinkLed.BackColor = Color.AliceBlue;
}
}
Do you think it's better?
What about the changing thread?
If I had a button:
private void PutValueInGraph1()
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
listBox1.Items.Add(ValueToAdd.ToString());
graph1.Series["Data1"].Points.AddY(ValueToAdd);
if (graph1.ChartAreas[0].AxisX.Maximum-10 > graph1.ChartAreas[0].AxisX.ScaleView.Size)
{
graph1.ChartAreas[0].AxisX.ScaleView.Scroll(graph1.ChartAreas[0].AxisX.Maximum);
graph1.Series["Data1"].Points.RemoveAt(0);
}
}
private void button1_Click(object sender, EventArgs e)
{//try to raise exception
PutValueInGraph1();
}
and I change the event like this:
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{//try to raise exception
PutValueInGraph1();
}
The data input accelerate when I'm started the timer and I click all the time on the button1.
Why is there no exception as tom_imk said??
because we can access the same function at the same time....?
Thanks for your answers.
I tried below sample code and it is working fine for me.
public Form7()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
chart1.ChartAreas[0].AxisX.Maximum = 100;
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Interval = 1;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
Random Rand_Value = new Random();
int ValueToAdd = Rand_Value.Next(1, 100);
chart1.Series[0].Points.AddY(ValueToAdd);
}
I'm surprised you didn't get an exception. You are manipulating UI elements outside the UI thread, something you musn't do, ever.
Refer to the answer in this question:
How to update the GUI from another thread in C#?
EDIT:
To make clear why the timerelapsed method does not run on the UI thread: It's simply the wrong class that is used here. So the easy solution would be to not created a System.Timers.Timer in the Form-constructor but to drop a timer on the form in the form designer and use that instead. The solution by sowjanya attaluri should be marked as the correct answer.
I am trying to make pictureboxes fall continuously in the form.
Here is the code that I tried.
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 Rain_dropz
{
public partial class Form1 : Form
{
PictureBox[] RD = new PictureBox[500];
int ndrop = 0;
public Form1()
{
InitializeComponent();
}
public void dropIt()
{
for (int i = 0; i < ndrop; i++)
{
RD[i].Top += 10;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Random rnd = new Random();
int l = rnd.Next(1,545);
RD[ndrop] = new PictureBox();
RD[ndrop].BackColor = System.Drawing.Color.MediumBlue;
RD[ndrop].Size = new Size(5, 5);
RD[ndrop].Location = new Point(l, 0);
this.Controls.Add(RD[ndrop]);
ndrop++;
dropIt();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
}
}
I think it is better to delete the picture boxes which disappear from the form. How to do that?
You can remove it by removing the picturebox from form controls list.
private void timer1_Tick(object sender, EventArgs e)
{
Random rnd = new Random();
int l = rnd.Next(1,545);
RD[ndrop] = new PictureBox();
RD[ndrop].BackColor = System.Drawing.Color.MediumBlue;
RD[ndrop].Size = new Size(5, 5);
RD[ndrop].Location = new Point(l, 0);
RD[ndrop].LocationChanged += pb_LocationChanged;
this.Controls.Add(RD[ndrop]);
ndrop++;
dropIt();
}
void pb_LocationChanged(object sender, EventArgs e)
{
// FORM_LASTBOUND is the Y-Axis point after which you wanted to remove the picturebox.
if ((sender as PictureBox).Top > FORM_LASTBOUND)
{
this.Controls.Remove(sender as PictureBox);
}
}
I want my textbox1.Text to countdown for 30 minutes. So far I have this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Timer timeX = new Timer();
timeX.Interval = 1800000;
timeX.Tick += new EventHandler(timeX_Tick);
}
void timeX_Tick(object sender, EventArgs e)
{
// what do i put here?
}
}
However I'm now stumped. I checked Google for answers but couldn't find one matching my question.
Here's a simple example similar to the code you posted:
using System;
using System.Windows.Forms;
namespace StackOverflowCountDown
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = TimeSpan.FromMinutes(30).ToString();
}
private void Form1_Load(object sender, EventArgs e) { }
private void textBox1_TextChanged(object sender, EventArgs e) { }
private void button1_Click(object sender, EventArgs e)
{
var startTime = DateTime.Now;
var timer = new Timer() { Interval = 1000 };
timer.Tick += (obj, args) =>
textBox1.Text =
(TimeSpan.FromMinutes(30) - (DateTime.Now - startTime))
.ToString("hh\\:mm\\:ss");
timer.Enabled = true;
}
}
}
Easiest thing you can do, is use a 1 minute timer:
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 countdowntimer
{
public partial class Form1 : Form
{
private Timer timeX;
private int minutesLeft;
public Form1()
{
InitializeComponent();
timeX = new Timer(){Interval = 60000};
timeX.Tick += new EventHandler(timeX_Tick);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
minutesLeft=30;
timeX.Start();
}
void timeX_Tick(object sender, EventArgs e)
{
if(minutesLeft--<=0)
{
timeX.Stop();
// Done!
}
else
{
// Not done yet...
}
textBox1.Text = minutesLeft + " mins remaining";
}
}
}
If all you want to do is set the value of your Texbox to count down from 30 Minutes. You will first need to change your timer interval to something smaller than 30Minutes. Something like timeX.Interval = 1000; which will fire every second. then set up your event like so:
int OrigTime = 1800;
void timeX_Tick(object sender, EventArgs e)
{
OrigTime--;
textBox1.Text = OrigTime/60 + ":" + ((OrigTime % 60) >= 10 ? (OrigTime % 60).ToString() : "0" + OrigTime % 60);
}
Also in your button click, you must add the following line: timeX.Enabled = true; In order to start the timer.
Your code will only get one event fired, once the 30 minutes has passed. In order to keep updating your UI continuously you'll have to make the events more frequent and add a condition inside the event handler to tell the count-down to stop once 30 minutes has passed.
You can do the time calculations easily by using TimeSpan and DateTime.
You'll also want to make sure your UI code runs on the UI thread, hence the Invoke.
timeX.Interval = 500;
...
TimeSpan timeSpan = TimeSpan.FromMinutes(30);
DataTime startedAt = DateTime.Now;
void timeX_Tick(object sender, EventArgs e)
{
if ((DateTime.Now - startedAt)<timeSpan){
Invoke(()=>{
TimeSpan remaining = timeSpan - (DateTime.Now - startedAt);
textBox.Text = remaining.ToString();
});
} else
timeX.Stop();
}
try this hope this will work for u
set timer interval=1000
minremain=1800000; //Should be in milisecond
timerplurg.satrt();
private void timerplurg_Tick(object sender, EventArgs e)
{
minremain = minremain - 1000;
string Sec = string.Empty;
string Min = string.Empty;
if (minremain <= 0)
{
lblpurgingTimer.Text = "";
timerplurg.Stop();
return;
}
else
{
var timeSpan = TimeSpan.FromMilliseconds(Convert.ToDouble(minremain));
var seconds = timeSpan.Seconds;
var minutes = timeSpan.Minutes;
if (seconds.ToString().Length.Equals(1))
{
Sec = "0" + seconds.ToString();
}
else
{
Sec = seconds.ToString();
}
if (minutes.ToString().Length.Equals(1))
{
Min = "0" + minutes.ToString();
}
else
{
Min = minutes.ToString();
}
string Totaltime = "Purge Remaing Time: " + Min + ":" + Sec;
lblpurgingTimer.Text = Totaltime;
}
}
Every time a check box is checked I want to be able to add to the progress bar in increments. So lets say if 1 out of 4 check boxes is check than it will equal to lets say 25 percent of the progress bar. Moreover if you uncheck one of the 4 check boxes the progress bar will decrease accordingly. This is what I have to which I am stuck.
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void progressBar1_Click(object sender, EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
int num1 = progressBar1.Maximum / 4;
int num2 = progressBar1.Maximum / 4;
int num3 = progressBar1.Maximum / 4;
int num4 = progressBar1.Maximum / 4;
int numAns;
numAns = num1 + num2 + num3 + num4;
progressBar1.Value = numAns;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if(checkBox1.Checked == true)
{
}
else if (checkBox1.Checked == false)
{
}
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
}
private void checkBox3_CheckedChanged(object sender, EventArgs e)
{
}
private void checkBox4_CheckedChanged(object sender, EventArgs e)
{
}
}
}
You can just use the same event handler for all of your checkboxes without making 4 methods for 4 checkboxes...
private const Int32 TOTAL_CHECKBOXES = 4;
private static Int32 s_Checks = 0;
private void OnCheckedChanged(object sender, EventArgs e)
{
if (((CheckBox)sender).Checked)
++s_Checks;
else
--s_Checks;
progressBar.Value = s_Checks * (progressBar.Maximum / TOTAL_CHECKBOXES);
}
Scrap the ProgressBar1_click, and for each box simply add (if Checked) or subtract (if not) 25 from ProgressBar1.Value on CheckedChanged.
You can wire up the same event to all checkboxes. I added mine to a list, so that if you wanted to add more in the future, you could simply add the handler and add it to the list and you are done.
public Form1()
{
InitializeComponent();
checkBox1.CheckedChanged += CheckedChanged_1;
checkBox2.CheckedChanged += CheckedChanged_1;
checkBox3.CheckedChanged += CheckedChanged_1;
checkBox4.CheckedChanged += CheckedChanged_1;
checkboxesToCount.AddRange(new CheckBox[] {checkBox1, checkBox2, checkBox3, checkBox4});
}
private void CheckedChanged_1(object sender, EventArgs e)
{
progressBar1.Value = 100 * checkboxesToCount.Count((c) => { return c.Checked; }) / checkboxesToCount.Count;
}
Hey guys im trying to get a simple button masher up, What i want timer1 to do is mash keys in richtextbox1 for 30 seconds over and over, after 30 seconds Activate timer2, which will disable timer 1 and press keys in richtextbox 2 once, then wait 10 seconds and activate timer 1 again.
Im extremley new to c# but ive tried using timer 3 to stop timer 2 and start timer 1 again and it just messes it self up. The code ive tried is below. Any help apreciated...
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = true;
}
private void timer2_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox2.Text);
SendKeys.Send("{ENTER}");
timer1.Enabled = false;
}
private void timer3_Tick(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = false;
}
private void richTextBox2_TextChanged(object sender, EventArgs e)
{
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
I suggest to use just one timer, increment a state counter every second, and perform an action base on the current state.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
if ((0 <= this.state) && (this.state < 30)) // Hit text box 1 30 times.
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == 30) // Hit text box 2 once.
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((31 <= this.state) && (this.state < 40)) // Do nothing 9 times.
{
// Do nothing.
}
else
{
throw new InvalidOperationException(); // Unexpected state.
}
// Update state.
this.state = (this.state + 1) % 40;
}
The variant with two numeric up down controls.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
Decimal n1 = this.numericUpDown1.Value;
Decimal n2 = this.numericUpDown2.Value;
if ((0 <= this.state) && (this.state < n1))
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == n1)
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((n1 <= this.state) && (this.state < n1 + n2))
{
// Do nothing.
}
else
{
// Reset state to resolve race conditions.
this.state = 0;
}
// Update state.
this.state = (this.state + 1) % (n1 + n2);
}
If timer3 is running continuously, won't it start timer1 and stop timer2 at unpredictable times, without warning?
IOW, what starts and stops timer3?
As JustLoren pointed out, there might be a cleaner way to do this. Perhaps a single timer event and some controlling logic and flags, rather than trying to juggle three timers.