I'm working on a simple vector drawing app in C#/.Net. The drawing is done in a panel, but I'm not using the OnPaint() event for all of it - in fact the OnPaint() even just calls another method which actually draws everything in the document.
I tried to add double buffering, but when I set DoubleBuffered to true, the flicker issue is even worse. Why is this? If I want to double buffer the control, do I absolutely have to do all my drawing in the OnPaint() event, with the supplied Graphics object, instead of using Panel.CreateGraphics() and then drawing to that?
EDIT: This is the basic code I am using.
private void doc_Paint(object sender, PaintEventArgs e)
{
g = doc.CreateGraphics();
Render(ScaleFactor, Offset);
}
private void Render(float ScaleFactor, PointF offset)
{
foreach (Line X in Document.Lines) { DrawLine(X.PointA, X.PointB, X.Color, X.LineWidth); }
}
private void DrawLine(PointF A, PointF B, Color Color, float Width)
{
Pen p = new Pen(Color, Width);
PointF PA = new PointF(((A.X + Offset.X) * ScaleFactor), ((A.Y + Offset.Y) * ScaleFactor));
PointF PB = new PointF(((B.X + Offset.X) * ScaleFactor), ((B.Y + Offset.Y) * ScaleFactor));
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawLine(p, PA, PB);
}
The general idea is that the two variables, ScaleFactor and Offset, refer to the zoom level and pan level in the UI. g is a Graphics object.
Double buffering is a term used to describe a device with two buffers. The usage of multiple buffers increases the overall throughput of a device and helps prevents bottlenecks. For example, with graphics, double buffering can show one image or frame while a separate frame is being buffered to be shown next.
To enable double buffering, simply call the setDoubleBuffered() method (inherited from JComponent) to set the double-buffered property to true for any components that should use double-buffered drawing.
Double buffering in computer graphics In computer graphics, double buffering is a technique for drawing graphics that shows no (or less) stutter, tearing, and other artifacts. It is difficult for a program to draw a display so that pixels do not change more than once.
Double buffering provides two complete color buffers for use in drawing. One buffer is displayed while the other buffer is being drawn into. When the drawing is complete, the two buffers are swapped so that the one that was being viewed is now used for drawing.
g = doc.CreateGraphics();
That's the mistake. Double-buffering can only work if you draw into the buffer. The one that e.Graphics references. Fix:
g = e.Graphics;
Beware that Panel doesn't have double-buffering turned on by default. You'll need to derive your own. Paste this into a new class:
using System;
using System.Windows.Forms;
class BufferedPanel : Panel {
public BufferedPanel() {
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
}
Compile. Drop it from the top of the toolbox.
Personally I don't bother with the DoubleBuffered setting. I just draw everything to a bitmap and then in the paint event draw that bitmap on the screen.
Bitmap BackBuffer;
private void MainFormSplitContainerPanel1Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(MainFormSplitContainer.Panel1.BackColor);
if (BackBuffer != null)
e.Graphics.DrawImage(BackBuffer, positionX, positionY, SizeX, SizeY);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With