0

I'm currently developing a C# application. Right now I'm trying to realize a simple slider:

|--------------------------|
|                          |
|  |--------------------|  |
|  |                    |  |
|  |       Panel1       |  |
|  |       Panel2       |  |
|  |                    |  |
|  |--------------------|  |
|           x x x          |
|--------------------------|

I have two panels with exactly the same size. Panel1 is just needed for displaying a border and setting the boundaries for panel2 which is then dynamically exchanged.

If the second x is clicked, panel2 should move to the left and panel3 should come from the right and also move to the left.

Basically I have the following code:

Panel panel2 = panelArray[0];
Panel panel3 = panelArray[1];

The following code should now perform the slide:

for (int i = 0; i <= 100; i++)
{
    panel2.Location = new Point(panel2.Location.X - i, panel2.Location.Y);
    System.Threading.Thread.Sleep(10);
}

for (int i = 0; i <= 100; i++)
{
    panel3.Location = new Point(100 - i, panel3.Location.Y);
    System.Threading.Thread.Sleep(10);
}

Somehow the first panel is slided-out perfectly but panel2 is not sliding. It's just displayed after the loop is executed.

Any idea why panel2 isn't performing the slide? I'm using WinForms.

libjup
  • 4,019
  • 2
  • 18
  • 23

2 Answers2

1

Try adding Application.DoEvents in the body of your loop after the location change. The UI needs a chance to catch up.

John
  • 2,653
  • 4
  • 36
  • 57
0

The problem is that you're not allowing the message pump to run by forcing a sleep. The suggested Application.DoEvents triggers the message pump, but it isn't a good solution because your code still blocks most of the time and you may even run in infinite loops with this pattern (e.g. if DoEvents re-enters the event you're calling it from).

Instead of using Thread.Sleep you should rather use a (Winforms) Timer. This will solve the UI update problem and also keep the UI alive while the slider moves.

Lucero
  • 59,176
  • 9
  • 122
  • 152
  • Thanks for your answer but how can I use `Timer` in a loop? I mean I somehow have to pause the loop to produce a smooth slide... Maybe you could add a short code snipped? Thanks a lot! – libjup Jul 26 '12 at 20:42
  • The timer replaces the loop - on each timer event you move by one step and exit. The timer will be triggered by the interval you specify, giving you a movement about as smooth as with the delay you're doing manually now. – Lucero Jul 26 '12 at 20:45
  • Btw Application.DoEvents works fine ;) there is just one problem left: the panel has a size of 800px; if i move panel2 out i only have to move it 100px to the left. But if I let panel3 slide in there are 800px to be moved. How can I ensure that both slides are done at the same speed? I've already set `System.Threading.Thread.Sleep(1);` to 1 but it's still slightly slower than the first one... – libjup Jul 26 '12 at 20:46
  • @libjup Please read my answer again - I didn't say that `Application.DoEvents` doesn't seem to work, I said that it was a bad solution and explained why. Sleeping isn't an exact business, the resolution is quite coarse. Read the docs for [`Sleep` (link)](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx). And this may also be of interest: http://stackoverflow.com/questions/7614936/can-i-improve-the-resolution-of-thread-sleep – Lucero Jul 26 '12 at 20:57
  • I see what you are saying but I still don't get how the timer knows when his job is done... I mean the loop is finished as soon as the counter reaches 100. But the timer seems to execute his eventHandler forever? I could use a condition to check whether the final-position of the panel is reached but the timer would still check that every 10 ms. – libjup Jul 26 '12 at 21:00
  • @libjup, you can disable (and re-enable) the timer at any time - just do that when you're done. – Lucero Jul 26 '12 at 21:04