Purpose of this code was to move a title(label) first rightwards until it hits the 600th pixel on the X axis and then leftwards until it hits the 27th pixel on the X axis of the form by using 2 timer tools and the Point class. One timer for going right and the other timer for going left. They should've work by swithing on and off consecutively after one another, however it does not work.
The label is stuck at 600th X location and does not move back to where it was.
The timer interval is 100 so it moves with a decent speed that allows us to see it moving.
namespace AlanCevreHesabiUygulamasi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
if (label11Point.X == 27)
{
timer2.Stop();
timer1.Start();
}
if (label11Point.X == 599)
{
timer1.Stop();
timer2.Start();
}
}
Point label11Point = new Point(27, 32);
private void timer1_Tick(object sender, EventArgs e)
{
while (label11Point.X <= 600)
{
label12.Text = label11Point.X.ToString();
label11Point.X = 1;
label11.Location = label11Point;
break;
}
}
private void timer2_Tick(object sender, EventArgs e)
{
while (label11Point.X >= 27)
{
label12.Text = label11Point.X.ToString();
label11Point.X -= 1;
label11.Location = label11Point;
break;
}
}
}
}
Label is stuck at 600th pixel of the form, does not move back. How to make it work?
CodePudding user response:
I solved it, I don't know why but in my opening post the Form1() function only makes one of the if() conditions work. However, putting the if() statements into the timers solved the problem. Now, the title goes back and forth in the specified x axis intervals.
namespace AlanCevreHesabiUygulamasi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Start();
}
Point label11Point = new Point(27, 32);
private void timer1_Tick(object sender, EventArgs e)
{
while (label11Point.X >= 27)
{
label12.Text = label11Point.X.ToString();
label11Point.X = 1;
label11.Location = label11Point;
break;
}
if (label11Point.X == 600)
{
timer2.Start();
timer1.Stop();
}
}
private void timer2_Tick(object sender, EventArgs e)
{
while (label11Point.X <= 600)
{
label12.Text = label11Point.X.ToString();
label11Point.X -= 1;
label11.Location = label11Point;
break;
}
if (label11Point.X == 27)
{
timer1.Start();
timer2.Stop();
}
}
CodePudding user response:
I'm surprised you see movement resulting from a while
loop in a timer tick handler. Why have a timer if your are going to do it that way.
In this solution, I have a timer, and the movements happen during a timer tick. I also have three possible directions, Right, Left and Stopped (in case you want to have a start/stop button).
In the Windows Forms designer, I dropped both a label and a timer on the form. I left their properties alone except for the timer's Interval
property (that I set to 10 (ms))
Then I added an enum and an instance of the enum as a field to the Form class:
public partial class Form1 : Form
{
private enum Direction { MoveRight, MoveLeft, Stopped }
Direction _direction;
public Form1()
{
InitializeComponent();
}
}
I double-clicked the Caption area of the form in the designer to create a form Load handler, and added a call to start the timer:
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
Finally, I double-clicked the timer to get a timer Tick handler and added some code:
private void timer1_Tick(object sender, EventArgs e)
{
var curLocation = label1.Location;
if (_direction == Direction.MoveRight && curLocation.X > 600)
{
_direction = Direction.MoveLeft;
}
else if (_direction == Direction.MoveLeft && curLocation.X < 27)
{
_direction = Direction.MoveRight;
}
int offset = _direction switch
{
Direction.MoveRight => 1,
Direction.MoveLeft => -1,
_ => 0,
};
curLocation.X = offset;
label1.Location = curLocation;
}
The _direction
field determines if the label is moving to the right or the left.
How can you write the code without a timer?"
You asked "How can you write the code without a timer?" I'm still flabbergasted that your label moves as the result of a while loop in an event handler - something must have changed from my good-old understanding of Win32 processing.
Anyways, I cheat and await
a call to Task.Delay
instead of using a timer. Take my existing code and do the following:
- Add two buttons to your form (One labeled Start (named
StartBtn
) and the other labeled Stop (namedStopBtn
). - Add another
Direction
-typed field to the class:Direction _previousDirection;
- Comment out the call to
timer1.Start();
in theForm1_Load
handler - Comment out all the code in the
timer1_Tick
method (at this point, you could remove the timer from the form if you want) - Select both buttons (Start and Stop) and press
<Enter>
. This will bring up click handlers for both buttons. - Change the StopBtn button's handler to look like:
New Stop Button code:
private void StopBtn_Click(object sender, EventArgs e)
{
_previousDirection = _direction;
_direction = Direction.Stopped;
}
- Change the StartBtn's handler to look like the following. Note that nearly everything in the
while
loop (except the call toTask.Delay
) is the same as the previous timer tick handler code. Also note that I made the handlerasync void
to allow for theawait
keyword to do it's magic.
Start Button code:
private async void StartBtn_Click(object sender, EventArgs e)
{
_direction = _previousDirection;
while (_direction != Direction.Stopped)
{
var curLocation = label1.Location;
if (_direction == Direction.MoveRight && curLocation.X > 600)
{
_direction = Direction.MoveLeft;
}
else if (_direction == Direction.MoveLeft && curLocation.X < 27)
{
_direction = Direction.MoveRight;
}
int offset = _direction switch
{
Direction.MoveRight => 1,
Direction.MoveLeft => -1,
_ => 0,
};
curLocation.X = offset;
label1.Location = curLocation;
await Task.Delay(10);
}
}