Is there a way to draw a line (or any shape) on a canvas, and then move that line?
I didn't see a way to do it, except maybe by constantly clearing and redrawing the entire canvas. Is that the only way?
That is the usual way - the canvas is tied to the update cycle of the view. SkiaSharp provides you with all the power, and does nothing.
If you have a complex drawing that takes a few milliseconds, and maybe could have areas cached, you can use temporary bitmaps. There is nothing stopping you from drawing to multiple bitmaps as things change, and then drawing all those bitmaps onto the screen when something needs updating.
Related
I create a custom control and draw some objects in OnRender.
Now the question is: Assume I draw 5 rectangles in OnRender. Is there a way to delete eg the 1. rectangle without to retrigger OnRender and redraw rectangles 2-5?
Or in general, is there another way, where you can update or add/remove rendering instructions, instead of rebuilding the drawing in OnRender every time something changes?
# dsdel: Ok, the idea is, that the calculations in OnRender might be very heavy. You can render Text, Geometric shapes. And I ask myself, why shall I create all the Geometry and FormatedText again, if the only thing I want, is to change the position of a line. The Rectangles above just were an example. It is more a general question. Is it really necessary to recalculate all elements in a new call to OnRender instead of just updating what has changed. I mean OnRender does not render anything, it just prepares some object structures that get transfered to DirectX for rendering. So I just want to manipulate the existing object structures instead of creating new once every time a little thing changes.
I'm working on a college project (simulation) that needs to draw a lot of lines and objects to a custom UserControl. My current approach is just to redraw everything for every tick / update loop using Invalidate(). But it sure needs a lot of time to draw (which is resulting in very low FPS) especially when I need to draw thousands of lines and rectangles.
So how can I only re-draw a specific (group of) objects that move in every update loop and only re-draw the rest (the rarely updated objects) when needed? Or is there other way to optimize the way I draw in this problem?
My idea would be the following:
Draw your Control onto a Bitmap (or other image format) once, and save that Image. Then display that Bitmap on your Control. (Assuming you use a Control that can do that, i.e an ImageBox, not sure what would be best for that).
Whenever you update your graphic, keep track of what sections of your Control may be outdated, then redraw only these sections (drawing only the objects that touch that section), and copy the other sections from your saved image.
Display (and save) the new Image.
I'm working with a WPF Canvas that contains a lot of elements. It needs to be able to pan and zoom. WPF cannot handle the layout of the canvas since it has too many elements (I don't know how many, but the XAML file is above 20mb).
The canvas is zoomed and panned using scale and translate transforms on the canvas' rendertransform.
A good trick I found is to use CacheMode. This fixes all panning problems as I generate a cache for the zoom level and set that. Easy, like this:
canvas.CacheMode = new BitmapCache(scale);
The problem is that I need to do it every time the scale changes (which is when the user zooms).
I understand that it will take some time to render the canvas and that is probably unavoidable. But how do I move that rendering to another thread so that it doesn't block the whole UI?
I understand the concept of Background Workers and Dispatcher and such, but I'm not sure how to handle this when the task that actually takes up all the time is the setting of a property that I can only access in the UI thread.
Is it possible to somehow generate the cache in another thread and then transfer it to the UI somehow?
Any other good ideas on how to lessen impact on the UI?
I'm looking to teach myself better methods of doing things in WPF that I would normally do manually.
In this case, I have a ViewBox with an image in it. I also have a button that uses a DoubleAnimation to rotate the image 90 to the right.
This animation works fine, but obviously because it's square as it turns, the image does a "best fit" to the ViewBox which makes the rotation look quite bad, as it gets larger and smaller as its longest edge shrinks or grows to fit to that particular rotation angle.
I am looking for any advice on the best way to handle this using appropriate WPF methods. Obviously I could do all the calculations manually, but I would be more interested in finding a way to use the controls and methods built into the .NET architecture.
Thanks for your help.
If you only have an Image in your ViewBox, drop the view box. An image is already capable of stretching correctly with the Stretch attribute set to Uniform.
In any case, use a RenderTransform instead of a LayoutTransform, to avoid recalculating the position of the controls when the images rotates. RenderTransform will rotate the object after all position calculations are done so you'll be fine. Just add a margin around the image if you find that it pass over some control while rotating.
What is the best approach to render a large number of 2D graphical elements (lines, text, shapes, etc.) in a scrollable view on windows using C#?
You could put a PictureBox (of whatever overall size required) onto a Panel with AutoScroll set to True, and then draw everything you need at once onto the PictureBox using a Graphics object.
However, if the overall size of the drawing surface is extremely large, this approach would not be practical (since it would mean having a huge PictureBox and a correspondingly huge Bitmap, which could consume a large amount of memory). If this were the case, you'd be better off creating your own scrollable user control (horizontal and vertical) and rendering only the visible portion of the overall surface in the control's Paint event.
The first approach would be easier and faster to write, but might consume too much memory. The second approach would require more work on your part, but would minimize memory consumption.
There is a scrollviewcontainer control but not on the toolbox by default. I would do the above approach to a picture box and embed it inside this control. Also, you can use SetStyle to enable double buffering to prevent flicker. Another option is to build a class to handle double buffering (draw to a bitmap object and push out the results using CreateGraphics). There are some good examples out there.