I am currently working on a C# winforms graphing application. To get right to the point, the Paint event handler for my graphing control has to plot thousands of points which can take several seconds. During this time the application is frozen. My goal is the following: if the user changed what data to be plotted while the older data is being plotted then it would stop in the middle of drawing the older data and start drawing the new the data. What is the proper way to do this or is this something else I am total missing? I tried to make my question as clear as possible.
The answer to you question lies in double buffering. You don't need to know all the details about double buffering to use it. Simply set the property to true like below to enable it within a control.
MyGraphPanelControl.DoubleBuffered = true;
The obvious draw back is memory usage but it will greatly increase the "speed" of things drawn on the panel. Like a lot of things in Computer Science, you trade memory for speed and visa versa.
Also, reading this from Microsoft will give you more insight in how to use Double Buffering.
Related
Hello: I am trying to create an app which will display a moving sphere. App will vary speed and direction. I've tried Adobe Flash but cannot get it smooth. Smoothness is essential in this case. So I am trying C#.
Initially, I can see that this can be implemented by:
1) Creating a PictureBox of a sphere, and using a Timer, change its coordinates. or
2) Using the this.paint function to draw a filled circle, and somehow, with a timer, erasing and redrawing it.
Can someone recommend the best path to take? I'll have a main menu where the user will chose speed/direction/how many etc... and then simply show the "game window" with the moving spheres. Any guidance would be much appreciated.
This is to be displayed on a PC only.
Thanks
-Ed
I just answered a similar question here.
NOTE: Depending on your needs, it is possible to achieve smooth animations under winforms (under certain conditions) though you are responsible for everything. wpf provides an animation framework but wpf is perhaps a milestone harder.
It probably does not matter should you pursue winforms first or WPF. You arguably could learn the basics under winforms then move over to wpf. wpf may require you to learn quite a bit before you can do anything.
Summary
Essentially what this does is to create an offscreen bitmap that we will draw into first. It is the same size as the UserControl. The control's OnPaint calls DrawOffscreen passing in the Graphics that is attached to the offscreen bitmap. Here we loop around just rendering the tiles/sky that are visible and ignoring others so as to improve performance.
Once it's all done we zap the entire offscreen bitmap to the display in one operation. This serves to eliminate:
Flicker
Tearing effects (typically associated with lateral movement)
There is a Timer that is scheduled to update the positions of all the tiles based on the time since the last update. This allows for a more realistic movement and avoids speed-ups and slow-downs under load. Tiles are moved in the OnUpdate method.
If you note in the code for Timer1OnTick I call Invalidate(Bounds); after animating everything. This does not cause an immediate paint rather Windows will queue a paint operation to be done at a later time. Consecutive pending operations will be fused into one. This means that we can be animating positions more frequently than painting during heavy load. Animation mechanic is independent of paint. That's a good thing, you don't want to be waiting for paints to occur. xna does a similar thing
Please refer to my full SO answer complete with sample code
Here are a few hints to get you going:
First you will need to come to a decision about which platform to target: WPF or Winforms.
Then you should know what to move across what; a nice Bitmap or just a circle across an empty background or a Bitmap or a Form with controls on it.
In Winforms both your approaches will work, esp. if you set a circular region see here for an example of that. (The part in the fun comment!)
And yes, a Timer is the way to animate the sphere. Btw, a Panel or even a Label can display an Bitmap just as well as a PictureBox.
For smooth movements make sure to set the Form.Doublebuffered=true, if you move across a Form. If you move across any other control (except a PictureBox or a Label) you will need to subclass it to get access to the DoubleBuffered property!
It is often also a good idea to keep the Location of a moving item in a variable as a PointF and use floats for its speed because this way you can fine grain the speed and Location changes and also the Timer Intervals!
I am tasked to write a .NET application that displays a slide-show with some information (words or images) and when the user sees certain items, s/he must immediately press space and the time of the key press must be recorded. The items will be displayed one after the other, for about 50ms. I need then to evaluate the difference between the timestamp of the keypress and and the one when the slideshow started (so I will know how long it took the user to react on the presented item). Edit: I must also record the time of the occurence of the special item.
I need to reduce any unpredictable lags that may occur as the application is running, so that the input processing is as realistic as possible, as well as to reduce any lags between the slides. Currently I am thinking of 3 approaches:
Write a standard Windows Forms (GDI+) application.
Write a WPF application
Write a DirectX-enabled windows forms application that utilizes the Tom Miller's Render loop concept (it is praised as effective in terms of performance).
Something else that you might suggest
I must clarify that I will not use advanced display techniques, special effects or designed for the purpose 3D environments - just plain text slides in different fonts and colours, or images. Unfortunately I cannot cite my sources, but I have read that Windows Forms and GDI+ cannot provide me with the desired accuracy. So, is WPF going to provide me with a better solution? Do I need to use the render loop, or some other approach. I am not experienced in such type of performance requirements for desktop applications, and all advices will be appreciated greatly.
I personally love WPF, but I would be very wary of using it for this application. It is not going to have the same time precision as GDI+ or DirectX. There are all sorts things you'll have to work with like the DispatchTimer and it just wasn't build for something like this. WPF is a whole set of gigantic abstractions on top of graphics and the farther you get away from the metal, you're introducing potential problems. If you want to put a video projected on top of a 3D sphere inside a combobox then WPF is the way to go, but if you need accuracy/precision on the scale you're talking, WPF is not the answer. I don't know where you read that WPF will provide you with better accuracy, I can practically guarantee that it will not.
DirectX would most likely be the most accurate in ensuring that a picture is only displayed for 50ms at a time. But GDI+ would be a decent alternative solution because it will make it easier to deal with text from a programming perspective.
Another consideration, screen refresh rates. yikes. if you do the math most LCDs have a 5ms response rate which is 10% of your allotted time. That and they only display at 60Hz. If you're displaying 20 pictures per second (50ms per picture) it is only going to be on the screen for 3 refresh cycles.
I hope this helps.
50 msec isn't long. Maybe encode and play the slideshow as a video?
I'm trying to make a picturebox move smoothly across a winform and the only way it even looks smooth is if I use a timer and lower the pixel speed to 1 px per 1 microsecond, and even then the movement of the picturebox is slow.
How do I use microseconds to make the picturebox move alot faster while still maintaining the level of smoothness when moving?
First I have no idea what your asking so maybe this will help maybe not.
Timing is a tricky issue. First All of the .net timers are at the milli second resolution and below that you have no assurance what the system is returning you with out using some type high resolution timer. The .net stopwatch uses the underlying high resolution timer but does not have a call back mechanism so you will need to build that your self utilizing a different thread and polling. That said you may want to look at animating in a different fashion then moving a picture box such as using bit blt or overloading the low level paint.
I'd imagine that moving a control across a form is a reasonably slow operation; so it's not that your timer isn't fine grained enough, it's going to flicker anyway. Rather than moving a picture box, you could paint whatever you had in the picture box onto the form background in the Paint event instead, changing the position you draw it to when a timer ticks. This way you could take advantage of things like double buffering for more smooth animation. You'll find that even a comparatively large interval like 40ms (25Hz refresh) should be enough in this case.
I am trying to create a simple rigid body 2D physics engine.
I was able to create a rectangle image by using four lines and able to manipulate the image according to its angle and position; I can move and rotate it (though I made it possible to rotate I do not use the rotating function since I am unable to comprehend angular momentum theory yet).
The image will fall and bounce back based on simple formula:
v(velocity) += a(acceleration)
x += v(velocity)
But I have to click a button every time I want execute a movement.
I want it to execute itself automatically and update automatically, I tried to use loop but for some reason program seems to stop during the time it is in loop section. And because I use an infinite loop that will start over and over again, my program just freezes.
Not only this is the problem but also my good friend, who has better knowledge in physics, told me that I should be able to calculate the amount of time if I want to make this engine work properly.
I like DJ KRAZE's comment - use a System.Windows.Threading.DispatcherTimer, and set the interval to however often you want the picture to redraw. On the timer's Tick event, do your redraw.
If you want to know why the simple loop doesn't work, you have to know a little bit about the Windows message loop. For a brief and somewhat inaccurate overview, all of stuff running in your application, it sounds like, is happening on one thread. Windows uses a message WM_PAINT, which goes through the message loop, to make the control paint itself. It only processes on message at a time.
Where you have your infinite loop, that is happening in the processing of some message. So this keeps the message loop from processing any messages, including messages for the controls to paint. So you don't see anything updating in your infinite loop.
Perhaps you could look into XNA, it's a Microsoft platform that facilitates games development, you should go to the App Hub for information on how to get started.
As for your specific question on refreshing the screen, you can take a look at the Update and Draw methods. Here's a tutorial that, although may not address your specific question, should give you the know-to on how to refresh the screen.
I am trying to plot data on a PDA that is being collected in real time via the bluetooth serial port using c# and windows mobile 5. I am having trouble plotting the data in such a way that it appears smooth. I have tried drawing a line from an array of points which worked but only really displayed discrete chunks of data. I found a similar solution on this forum in reference to ECG data, which also worked but again it showed some amount of data and then very visibly refreshed. I have tried drawing the points onto a bitmap and then painting the bitmap to make it smoother but again it isn't really fast enough.
What I would like to end up with is something that behaves like the CPU usage history graph in the windows task manager. A data point starts on the right hand side of the plot and moves smoothly across to the left. Is there a standard approach to a problem like this? I apologise if the question is a little vague but I don't want to spend ages trying different things if its a problem with a well known general solution.
It kind of depends on how you want it to work visually. The CPU usage in Task Manager scrolls the entire chart right to left, and it is not at all smooth. It's refreshing (for me anyway) about once a second and when it refreshes, then entire chart "bumps" to the side.
I did something in the CF back in the 1.0 days as a test, and I opted to have the chart remain static and have the data lines continuually drawn left to right and when it reached the right edge, it would start drawing again back on the left, erasing the oldest chart data as it progressed (like an ECG does).
For that scenario, your bitmap is remaining largely unchanged, so you shouldn't be redrawing the entire thing. I did this by using a clipping resion that was basically a "vertical band" or rectangle the height of the chart but only, say, 10px wide. I redrew that band with the updated axis values so the only bits actually being redrawn is that small band. It also had the added benefit of doing the visible "erasing" the oldest data once I wrapped back to the start of the chart.