How can I set time to run a for loop?
I'm going on fade a form on close and this is my code:
Time ftmr=new Timer();
//set time interval 5 sec
ftmr.Interval = 5000;
//starts the timer
ftmr.Start();
ftmr.Tick += Ftmr_Tick;
private void Ftmr_Tick(object sender, EventArgs e)
{
for (int i = 0; i <= 100; i++)
{
this.Opacity = 100 - i;
this.Refresh();
}
Dispose();
}
There are several things wrong in your code. First, you shouldn't use a loop to set the Opacity since it will only really do something after the event is handled entirely. Let the timer do the looping. Second, don't Dispose your form in the timer. It will get rid of all UI elements, so you can throw your form away...
Try this:
Time ftmr=new Timer();
//set time interval 5 sec
ftmr.Interval = 5000 / 100; // 100 attempts
//starts the timer
ftmr.Start();
ftmr.Tick += Ftmr_Tick;
double opacity = 1;
private void Ftmr_Tick(object sender, EventArgs e)
{
this.Opacity = opacity;
opacity -= .01;
this.Refresh();
if (this.Opacity <= 0)
{
ftmr.Stop();
}
}
Note that this code will take longer than 5 seconds to run due to the way the timer works. You might need to tweak the numbers a little bit.
This is one of the few cases where it is acceptable to hang the UI thread and use Thread.Sleep() instead. The Opacity property is immediately effective and doesn't require a repaint. Do so in the FormClosing event.
Be sure to start with the Opacity set to 0.99 so you don't get flicker from the native window getting re-created. Five seconds is too long, both to the user and the operating system, about a second is reasonable. For example:
public Form1() {
InitializeComponent();
this.Opacity = 0.99;
}
protected override void OnFormClosing(FormClosingEventArgs e) {
base.OnFormClosing(e);
if (!e.Cancel) {
for (int op = 99; op >= 0; op -= 3) {
this.Opacity = op / 100f;
System.Threading.Thread.Sleep(15);
}
}
}
}
Related
I have a winform application and I need to make the label backcolor blinking. I am trying to do that using a for loop and a Thread.Sleep, but does not work. Thank you for any help and advise:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(1000); // Set fast to slow.
if (label1.BackColor == Color.Red)
label1.BackColor = Color.Transparent;
else
label1.BackColor = Color.Red;
}
}
Use a UI timer, not sleep for this task. You're putting the main thread to sleep all the time and you're blocking user input with that. Using Thread.Sleep is almost always a sign that you're doing something wrong. There are very few situations when Thread.Sleep is correct. Specifically, putting the UI thread to sleep is never correct.
Put a Timer component on your form and in the Tick event, keep changing the background color of your label.
For example:
// Keeps track of the number of blinks
private int m_nBlinkCount = 0;
// ...
// tmrTimer is a component added to the form.
tmrTimer.Tick += new EventHandler(OnTimerTick);
m_nBlinkCount = 0;
tmrTimer.Interval = 1000; // 1 second interval
tmrTimer.Start();
// ...
private void OnTimerTick ( Object sender, EventArgs eventargs)
{
if (label1.BackColor == Color.Red)
label1.BackColor = Color.Transparent;
else
label1.BackColor = Color.Red;
m_nBlinkCount++;
if ( m_nBlinkCount >= 10 )
tmrTimer.Stop ();
}
What's happening here is that you are sleeping the GUI thread, which causes the program to hang. The GUI thread is also the thread that would be responsible for changing the background color of the label.
Here's a simple implementation that will solve this problem for you. Note that this isn't the best implementation possible, but it uses your preferred blink code implementation. For a better option than Thread.Sleep, see System.Timers.Timer or, as xxbbcc suggested, a System.Windows.Forms.Timer.
BackgroundWorker blinker;
public Form1()
{
InitializeComponent();
blinker = new BackgroundWorker();
blinker.DoWork += blinker_DoWork;
}
private void blinker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(1000); // Set fast to slow.
if (label1.InvokeRequired)
{
label1.Invoke((Action)blink);
}
else
{
blink();
}
}
}
private void blink()
{
if (label1.BackColor == Color.Red)
label1.BackColor = Color.Transparent;
else
label1.BackColor = Color.Red;
}
private void button1_Click(object sender, EventArgs e)
{
if (blinker.IsBusy == false)
{
blinker.RunWorkerAsync();
}
}
comboBox selectedindexchanged event:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
updateTime = Convert.ToInt32(comboBox1.SelectedItem);
xpProgressBar1.Position = 0;
counter = 0;
panel1.Select();
}
Update method:
public void Update()
{
counter += 1;
int position = (int)Math.Round((counter / updateTime) * 100);
xpProgressBar1.Text = counter.ToString() + " %";
xpProgressBar1.Position = position;
if (counter == 10)
{
if (!backgroundWorker1.IsBusy)
{
timer1.Stop();
backgroundWorker1.RunWorkerAsync();
}
counter = 0;
}
}
Timer tick event:
private void timer1_Tick(object sender, EventArgs e)
{
Update();
}
In the combBox by default it's on the first item the number 10 then i can change and select the item with the number 30,50,60,120,300 and all this values are in seconds.
The timer1 interval is set to 1000
The problem is when it's on 10 by default when running the program or if i change it back to 10 in the comboBox it's working good. What it does it's counting 10 seconds and updating the progressBar(xpProgressBar1) by 10's i mean each second the progressBar move by 10 percentages. So after 10 seconds it's getting to 100 percentages.
But when i change the comboBox to the second item to 30 it should count now 30 seconds untill 100%
So i'm not sure in what steps it should move and how to do it. Same if i change it to 120 then it should move progress 120 seconds and again i'm not sure what steps and how to do it so it will get to 100%
What it does now for example if i change it to 120 i see it start counting to 120 by steps of 1 but then when it's getting to 10% it's jumping back to the start and not continue.
It should keep counting the whole 120 seconds untill 100%
If i change it to 30 i see it also counting by steps of 1 each time but again in 10% it's jumping to the start and not continue.
When it's on 10 it's counting by steps of 10 untill 100% so i wonder what should i do and how in the others if it's on 120 to step by 120 ? not logic. So tmake them all to step by 1 also the when it's on 10 ? And again how to do it so it will not stop a 10% and start over again.
Now i changed in the Update method the line if (counter == 10) to:
if (counter == updateTime)
So now if i change in the comboBox select 120 it will count in steps of 1 untill 120 but now when it will get the progressBar to 100% it will keep counting untill 120.
There is no sync between the 120 seconds and the 100% of the progressBar.
EDIT
The Update method:
private int _updateCounter;
public void Update()
{
counter += 1;
xpProgressBar1.Text = counter.ToString() + " %";
xpProgressBar1.Position = _updateCounter++ * 10;
if (counter == 10)
{
if (!backgroundWorker1.IsBusy)
{
timer1.Stop();
backgroundWorker1.RunWorkerAsync();
}
counter = 0;
}
}
This is called prescaler (frequency divider). You have single clock source (Timer) with fastest frequency using which you can achieve needed frequencies by skipping certain calls (events).
All you miss is that skipping:
private int _timer1Ticks;
private void timer1_Tick(object sender, EventArgs e)
{
if(_timer1Ticks++ >= int.Parse(comboBox1.Text) / 10)
{
_timer1Ticks = 0;
Update();
}
}
This way Update will be called exactly 10 times, disregard of combobox selection.
And to calculate progress:
private int _updateCounter;
public void Update()
{
xpProgressBar1.Position = _updateCounter++ * 10;
...
// do not forget to stop timer
if(_updateCounter == 10)
{
timer1.Stop();
_updateCounter = 0; // add some cleanup if using timer more than once
_timer1Ticks = 0;
...
}
}
I am making a Q&A program where you have 15 sec to answer a question. The problem is that the progress bar is only filling like 90% and moves to the next question. I can put the code here but I have worked in Dutch so maybe it's difficult to understand.
private void volgendeVraagFormButton_Click(object sender, EventArgs e)
{
//button for going to next question
vraagFormulierProgressBar.Value = 0;
vraagFormulierTimer.Start();
}
private void vraagFormulierTimer_Tick(object sender, EventArgs e)
{
if (vraagFormulierProgressBar.Value < vraagFormulierProgressBar.Maximum)
vraagFormulierProgressBar.PerformStep();
//checks if the value is lower than 15 sec(max)
else
{ //stops the progress if the 15 secs are over and moves to next question
vraagFormulierTimer.Stop();
vraagFormulierProgressBar.Value = 0;
vraagFormulierTimer.Start();
}
}
Here's the same code with variable names in English:
private void nextQuestionFormButton_Click(object sender, EventArgs e)
{
//button for going to next question
questionFormProgressBar.Value = 0;
questionFormTimer.Start();
}
private void questionFormTimer_Tick(object sender, EventArgs e)
{
if (questionFormProgressBar.Value <questionFormProgressBar.Maximum)
questionFormProgressBar.PerformStep();
//checks if the value is lower than 15 sec(max)
else
{ //stops the progress if the 15 secs are over and moves to next question
questionFormTimer.Stop();
questionFormProgressBar.Value = 0;
questionFormTimer.Start();
}
}
Take a look at this: Disabling .NET progressbar animation when changing value?
So try to increment your progress bar by 2, then decrement by 1. That should fix the animation problem
Edit
Also, change this line
if (vraagFormulierProgressBar.Value < vraagFormulierProgressBar.Maximum)
to this
if (vraagFormulierProgressBar.Value + 1 < vraagFormulierProgressBar.Maximum)
Edit 2
OK, I've got it this time. First, set the maximum of your progress bar to 300 and the interval to 1 (You can fix the timing later). Next, replace the timer tick function with this:
if (progressBar1.Value < progressBar1.Maximum - 1)
{
progressBar1.Increment(2);
progressBar1.Increment(-1);
}
else
{
timer1.Stop();
progressBar1.Maximum = 10000;
progressBar1.Value = 10000;
progressBar1.Value = 9999;
progressBar1.Value = 10000;
System.Threading.Thread.Sleep(150);
progressBar1.Value = 0;
progressBar1.Maximum = 300;
timer1.Start();
}
Sorry about using the English names, I copied this out of my test form. Anyway, hope this helps!
I am trying to fill a rectangle in 3 seconds of real time
I want the increment to be a constant value to look nice and not have acceleration
and I am having trouble understanding what to do
this is my code
// constant
// 1.0f = 100% of rectangle, 3 sec = 3000.0 miliseconds
float addValue = 1.0f/3000.0f;
public override void Update(GameTime gameTime)
{
newGameTime += gameTime.ElapsedGameTime.Milliseconds;
// once the percentage is set to 0 this starts
if ((percentage < 1))
{
// calculate value here in order to time
percentage += addValue;
}
}
I've been trying all kind of crazy math to get it right but i completely lost it. :(
I know I should be using gameTime or newGameTime but I'm lost
I assume thats your update / rendering function.
Let's say, for example, that since the last rendering, 300ms elapsed. That means you'd have to add 100%/3000ms * 300ms = 10% to your rectangle.
-> You're missing the elapsed time in the calculation:
percentage += addValue * gameTime.ElapsedGameTime.Milliseconds;
I may be completely wrong with this answer according to what ccKep just mentioned in his comment.
But just in case it's what you're looking for, I put this together.
The main idea is having a timer event controling the increment. Even if the code I'm submitting isn't appropriate, maybe the idea will apply.
public int percentage;
public int Percentage
{
get { return percentage; }
set
{
percentage = value;
if (Percentage >= 0 && Percentage < 100)
{
progressBar1.Value = value;
}
else
{
Percentage = 0;
timer1.Stop();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Percentage = 0;
timer1.Interval = 1000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
double addValue = 100 / 3;
Percentage += (int)addValue;
}
I have a single form window application now I want to change the form opacity when application runs. Means when application run it will show low opacity form and as time increse it will show complete form with 100 opacity. So how to do that. (should I use timer control to control opacity, if yes then how????)
in constructor of the form you can write something like this.
this.Opacity = .1;
timer.Interval = new TimeSpan(0, 0, intervalinminutes);
timer.Tick += ChangeOpacity;
timer.Start();
And then define a method like this
void ChangeOpacity(object sender, EventArgs e)
{
this.Opacity += .10; //replace.10 with whatever you want
if(this.Opacity == 1)
timer.Stop();
}
To fade forms in and out, I usually do this:
for(double opacity = 0.0; opacity <= 1.0; opacity += 0.2) {
DateTime start = DateTime.Now;
this.Opacity = opacity;
while(DateTime.Now.Subtract(start).TotalMilliseconds <= 30.0) {
Application.DoEvents();
}
}
It's a nice, simple solution if you'll be doing it very infrequently. Otherwise, I would recommend using threads.
In the constructor, start the timer control that will call a method at each tick.
timer.Interval = 1000;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Start();
............
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
if(this.Opacity < 1)
this.Opacity += .1;
else
timer.Stop();
}
For Exit Decreasing Opacity Animation
///////\\\\\\ Coded by Error X Tech ///////\\\\\\
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private void DecreaseOpacity(object sender, EventArgs e)
{
if (this.Opacity >= 0.1)
{
this.Opacity -= 0.04; //replace 0.04 with whatever you want
}
if (this.Opacity <= 0.0)
timer.Stop();
if (this.Opacity <= 0.1)
{
System.Environment.Exit(1);
Process.GetCurrentProcess().Kill();
}
}
private void Exit_Click(object sender, EventArgs e)
{
timer.Interval = 47; //replace 47 with whatever you want
timer.Tick += DecreaseOpacity;
timer.Start();
}
In the constructor, set the opacity to 0 and start a timer with an interval of something small like 10 or 100 milliseconds. In the timer_Tick event, you simply need to run this.Opacity += 0.01;
This will make it so that the opacity starts at 0 and increase by .01 every few milliseconds until it's 1 (opacity is a double, when it reaches a value of 1 it's fully opaque)
increasing Opacity Animation while Application start
///////\\\\\\ Coded by Error X Tech ///////\\\\\\
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
void IncreaseOpacity(object sender, EventArgs e)
{
if (this.Opacity <= 1) //replace 0.88 with whatever you want
{
this.Opacity += 0.01; //replace 0.01 with whatever you want
}
if (this.Opacity == 1) //replace 0.88 with whatever you want
timer.Stop();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Opacity = .01;
timer.Interval = 10; //replace 10 with whatever you want
timer.Tick += IncreaseOpacity;
timer.Start();
}