Animate the Text property of a TextBlock - c#

I am quite new to WP develoment and am currently playing around with animations.
What I am now trying to do is animate the Text property of a TextBlock.
For training purposes, I am developping a simple temperature convertion app and there is a big number on the screen (the temperature) that I would like to gradually increase or decrease until it reaches another value (for instance from 10 to 24 by displaying every number inbetween).
I tried using a storyboard on the text property but as I thought it doesn't work. Then I tried setting the property to each value one by one (for loop) but the view dons't refresh regularly enough and the app blocks until the loop finishes and displays only the last value.
I don't know if what I would like to do is possible (I hope it is it's not that uncommon, right?) and I have no other idea to get the result I would like.
Does anyone has an idea about that?
Thanks :)

You may use a DispatcherTimer, and update the TextBlock's Text property in its Tick event handler:
private readonly DispatcherTimer timer = new DispatcherTimer();
private int currentValue;
private int endValue;
public MainPage()
{
...
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += TimerTick;
}
private void TimerTick(object sender, object e)
{
currentValue++;
textBlock.Text = currentValue.ToString();
if (currentValue >= endValue)
{
timer.Stop();
}
}
private void AnimateText(int start, int end)
{
currentValue = start;
endValue = end;
textBlock.Text = currentValue.ToString();
if (currentValue < endValue)
{
timer.Start();
}
}

Related

Hover effect CSS in a Button or Panel C# [duplicate]

I am trying to learn .NET programming. As a part of my learning, I tried to make some effects on buttons. It is working... but not as smooth as I imagined! Is there any better way to do this? Thank you in advance!
My need:
There are 3 buttons.
When you hover the mouse over one of them, it expands and when you mouse out from that button, it returns to its initial size.
private void button1_MouseHover(object sender, EventArgs e)
{
button1.BackColor = Color.White;
button1.Width = 130;
button1.BringToFront();
}
private void button1_MouseLeave(object sender, EventArgs e)
{
button1.BackColor = Color.Red;
button1.Width = 75;
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.BackColor = Color.Gray;
button2.Width = 130;
button2.BringToFront();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
button2.BackColor = Color.Red;
button2.Width = 75;
}
private void button3_MouseHover(object sender, EventArgs e)
{
button3.BackColor = Color.DimGray;
button3.Width = 130;
button3.BringToFront();
}
private void button3_MouseLeave(object sender, EventArgs e)
{
button3.BackColor = Color.Red;
button3.Width = 75;
}
So first off, you don't want to do the exact same thing 3 times. Create a single method to add the appropriate handlers for a button, and then just write the code once to handle any given button.
Note that you can go into the expand/contract tick handlers and use the percentComplete value to set the height as well, to move the color along a spectrum (this would involve some mathematics of colors to do though) or to alter any other aspect of the button. If you're really motivated to generalize it you could add a parameter to the method of Action<double> that does something to the object based on the given percent progress.
public void AddAnimation(Button button)
{
var expandTimer = new System.Windows.Forms.Timer();
var contractTimer = new System.Windows.Forms.Timer();
expandTimer.Interval = 10;//can adjust to determine the refresh rate
contractTimer.Interval = 10;
DateTime animationStarted = DateTime.Now;
//TODO update as appropriate or make it a parameter
TimeSpan animationDuration = TimeSpan.FromMilliseconds(250);
int initialWidth = 75;
int endWidth = 130;
button.MouseHover += (_, args) =>
{
contractTimer.Stop();
expandTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.DimGray;
};
button.MouseLeave += (_, args) =>
{
expandTimer.Stop();
contractTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.Red;
};
expandTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
expandTimer.Stop();
}
else
{
button.Width = (int)(initialWidth +
(endWidth - initialWidth) * percentComplete);
}
};
contractTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
contractTimer.Stop();
}
else
{
button.Width = (int)(endWidth -
(endWidth - initialWidth) * percentComplete);
}
};
}
If you are using WinForms, animations are going to be rather painful and you will have to handle them yourself via Timer objects.
If you are getting into .NET and want to make cool-looking applications with animatons and styling, I highly recommend you look at WPF instead. It can do animations very easily though C# or XAML.
While it is still possible in WinForms, it will take far more development time where as those features are built into WPF already (and optimized).
When you modify a controls properties, it takes effect instantaneously. What you desire is something that is usually known as some type of fade or tweening. There might be libraries out there to do this, but if you wanted to write this yourself for fun, you can use a Timer object, and on each tick update the color.
What you would do is set a color as the TargetColor somewhere(this is a variable or property you make up), and then start a timer that ticks maybe every 10 milliseconds. In each tick, you look at the start time, and how long has passed since then. If you want the animation to take place of a full second, then that is 1000 milliseconds. So during each tick, you look at the amount of time that has passed, maybe 200 milliseconds, then divide 200/1000 to get the fraction of time that you have gone into the animation. Then you look at a difference between the Start and Target Color, multiply that difference by the fraction, and add the result to the start color. In other words, 200 milliseconds into an animation that last 1000 milliseconds, means you are 20% into the animation. Thus you want to set the color to be whatever color is 20% from the start color towards the end color.
There's alot you could do to refine this. Perhaps having a subclass Button control that encapsulates the timer and exposes functions/properties to track start/end color, animation transition time, etc. Most animated UI features like this let you specify how long the animation should last, and then it interpolates the inbetween states as it transitions. This is the origin of the term tweening, as it comes from transitioning from one state to another by inbetweening

How to make DispatcherTimer show time in a textbox and perform action when reaches a certain time in C#?

This is my second question on StackOverflow here. I posted my first question a while ago and got a working reply in no time, much impressed, much appreciated.
Anyways, so what I want to know is, how to get a DispatcherTimer to work and show time in a certain textbox and stop it when it reaches a certain time (let's say 60 seconds) and perform a function after 60 seconds.
What I'm basically using this for is :
Making a game, which has to stop after 60 seconds and show the scores or related stuff. So this requires me to show the time in a textbox and perform a function at 60 seconds or after that.
Here's more information :
Textbox is called "timerbox"
Here's the code I've tried :
DispatcherTimer dt = new DispatcherTimer();
private void TimerStart(object sender, RoutedEventArgs e)
{
dt.Interval = TimeSpan.FromSeconds(1);
dt.Tick += dt_Tick;
dt.Start();
}
int count = 0;
void dt_Tick(object sender, object e)
{
count = count + 1;
timerbox.Text = Convert.ToString(count);
}
It doesn't show the time in textbox, plus I don't know how to make it stop at certain point and perform a function.
Thank you for reaching here, please leave answers with full explanation as I'm a complete beginner :)
P.S. I'm using Windows Store App Development Environment in Visual Studio 2013.
And there's no "Timer" in it as there is in normal C# Environment.
AOA.
I am recently started learning c#. (interested in windows form application). Hope this help you.
if you just want to set timer for a curtain event.....
recommend you using timer ( in toolbox )......
follow steps, when you double click on timer1 VS will create a timer1_Tick function for you which will be called every timer you timer ticks.....
now what you want to do when timer1 icks write it in there....like this....
private void timer1_Tick(object sender, EventArgs e)
{
//enter your code here
}
now write timer1. and VS will display a list of avaliable function....
for example,
timer1.Interval = (60*1000); //enter time in milliseconds
now when you want to start the write......
timer1.Start();
and to stop timer at any timer call
timer1.Stop();
if you want to repeat timer just write timer1.start() in that tick function.....
plus, to set textbox text equal to timer1 time use something like
textBox1.Text = Convert.ToString(timer1.Interval);
Click here for more information on timer class
hope this help you,
in case of any confusion, just comment,.....
The normal flow of a DispatcherTimer would look like this:
First Set up your new Object, set up the a new EventHandler that will run your desired code each Tick and Set the Timespan for the desired Tick Interval.
public MainPage()
{
this.InitializeComponent();
timer = new DispatcherTimer();
timer.Tick += new EventHandler<object>(timer_Tick);
timer.Interval = TimeSpan.FromMilliseconds(bpm);
}
Set The Timer_Tick Envent
async Void timer_Tick(object Sender, object e)
{
await this.Dispatcher.RunAsync(Windows.UI.core.CoreDispatcherPriority.High, () =>
{
//Run the Code
textBox1.text = timer.interval.TotalMilliseconds.ToString();
});
You have to have a trigger to Start the Dispatcher(and to stop if you need to), for example a button
private void StartButton_Click()
{
timer.Start();
}
This example was done using The new windows 10 Universal App platform within VS2015, but I think it should look about the same in a normal windows 8 App

C# Slow down random number GUI display

I have an application that generates random numbers for about 20 seconds and shows the random number on the fly in a label in the screen.
I want to show the numbers in the same label but then slow down the display of the numbers so like 5 seconds before stoping the process, the display of the number should smoothly slow down more and more until it stops in the final number. Like a raffle.
Any clue?
I can start by telling you what not do to. Do not use Thread.Sleep -- doing so is almost always a "worst practice" and will make your UI unresponsive.
If you use Thread.Sleep on a second thread, as mcl suggests, you won't freeze your UI but you are burning an extremely expensive thread to do very little work.
If you are using C# 4 or earlier then I would create a timer set to tick, say, four times a second. Handle the tick event, and if enough time has passed since the last tick event, change the label. Or, change the interval of the timer each time it ticks.
If you are using C# 5, you can just use await Task.Delay(x):
async void Animate()
{
int delay = 5;
for(int i = 1; i < 10; ++i)
{
UpdateLabel();
await Task.Delay(delay);
delay = delay * 2;
}
}
So now you start with a 5ms delay, then 10, then 20...
Here's a working program to get you started. It changes the Text of the Form for 3 seconds quickly, after which it gets slower. That's achieved by using one Timer to start decelerating the Timer which shows the random numbers.
public partial class Form1 : Form
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer() { Interval = 10 };
System.Windows.Forms.Timer timerForStartingSlowDown = new System.Windows.Forms.Timer() { Interval = 3000 };
bool slow = false;
Random random = new Random();
public Form1()
{
InitializeComponent();
timer.Tick += timer_Tick;
timerForStartingSlowDown.Tick += timerForStartingSlowDown_Tick;
Shown += Form1_Shown;
}
void timerForStartingSlowDown_Tick(object sender, EventArgs e)
{
slow = true;
timerForStartingSlowDown.Enabled = false;
}
void Form1_Shown(object sender, EventArgs e)
{
timer.Enabled = true;
timerForStartingSlowDown.Enabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
if (timer.Interval > 350) timer.Enabled = false;
else
{
if (slow) timer.Interval += 10;
Text = random.Next(1, 100).ToString();
}
}
}
Consider generating those numbers on a different thread. You can use BackgroundWorker for that and report the progress as you generate each number. When you begin to reach the end use Thread.Sleep(miliseconds) to "slow" (freez) the BackgroundWorker's job thread that is generating the numbers for a specified amount of miliseconds increasing those miliseconds as you aproach the final number. That should do the trick.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Set the BackgroundWorker to report progress and use that to "push" the generated number to the UI thread.
You can also drag and drop the BackgroundWorker component on your form from the Toolbox.

Make text scroll a given amount of times

I'm only just getting into GUIs, so please forgive me if I've missed something obvious. Google hasn't helped much I'm afraid.
My base objective is to have Marquee style text scrolling across the screen a set number of times. I've achieved the scrolling aspect utilizing a timer which scrolls a label named "My text here" across the screen (taken from this tutorial: http://www.youtube.com/watch?v=-y-Z0i-DeAs Note: I don't speak the language he does), but I've been unable to get the thing to stop. I'm open to using a different way to achieve the scrolling, but this is the only example I've found so far that worked well with my current level of knowledge of GUIs (basically dragging and dropping).
private void timer_Tick(object sender, EventArgs e)
{
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}
My best guess is that the timer is simply starting the whole process over with each tick. I've tried countering this by having it return after running i times and telling the label what to display, but that's not working. Nor can I seem to find a way to tell the thing to stop.
http://www.dotnetperls.com/timer has an example where a timer is set to run for a given amount of time, but I do not know how to implement that when messing around with GUIs. What would be the best way to implement the feature I desire? Any insight or suggestions would be greatly appreciated.
EDIT: Based on suggestions in the answers and comments I have edited the code to run for what should be 30 seconds before setting itself to a given position. However the text no longer scrolls. I'm going to keep working at it, but more input would be appreciated.
private void timer_Tick(object sender, EventArgs e)
{
var time = DateTime.Now;
if(time < DateTime.Now.AddSeconds(-30)) // you decide when to stop scrolling
{
Timer timer = (Timer)sender;
timer.Stop();
labelTesting.Left = 0; // or wherever it should be at the end of the scrolling
}
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}
You need to stop the timer:
private void timer_Tick(object sender, EventArgs e)
{
if (someConditionToEndScroll) // you decide when to stop scrolling
{
Timer timer = (Timer) sender;
timer.Stop();
labelTesting.Left = 0; // or wherever it should be at the end of the scrolling
}
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}

How to schedule a repeating task to count down a number in windows phone 8

I need to just have a simple task that runs as long as the user is on one specific screen.
On this screen there is a count down timer.
I looked into Background Agents - but that seems not to be the right approach.
Basically it should work like this: The user goes to this one screen, presses start and the cont down timer starts to count down - every 30 seconds update is perfectly ok.
How should I do this on WP8 ?
Many thanks!
You should use a DispatcherTimer as wkempf points out. Pretty simple to create actually. Something like this (where you have a TextBlock named countText in your xaml:
public partial class MainPage : PhoneApplicationPage
{
private DispatcherTimer _timer;
private int _countdown;
// Constructor
public MainPage()
{
InitializeComponent();
_countdown = 100;
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += (s, e) => Tick();
_timer.Start();
}
private void Tick()
{
_countdown--;
if (_countdown == 0)
{
_timer.Stop();
}
countText.Text = _countdown.ToString();
}
}
There are numerous Timers in .NET. System.Windows.Threading.DispatcherTimer is probably what you want, but System.Threading.Timer might be what you want as well. Depend on whether you want to run the periodic code in the background or on the UI thread.

Categories