Maxime C.
Maxime C.

Reputation: 35

How come the graphics is not drawing onto the panel

I want to draw a grid in my panel. The graphics object (screen) that i created with bitmap isn't drawing in my panel. I tried with debugging to look if the screen wasn't drawing but that wasn't the case.

I tried creating the graphic object from the panel createGraphic method and the parameter painteventargs from the panel paint method. Both times when I used it to draw it with OnPaint it took too long.

public Main()
{
    InitializeComponent();
    backBuffer = new Bitmap(drawPanel.Width, drawPanel.Height);
    screen = Graphics.FromImage(backBuffer);
    sizeGridPoints = 2;
    lenghtBetweenGridPoints = 10;
}

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    screen.Clear(Color.Black);
    DrawGrid();
}

private void DrawGrid()
{
    for(int x = lenghtBetweenGridPoints; x < drawPanel.Width; x += lenghtBetweenGridPoints)
    {
        for(int y = lenghtBetweenGridPoints; y < drawPanel.Height; y+= lenghtBetweenGridPoints)
        {
            screen.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);
        }
    }
}

Upvotes: 0

Views: 309

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112259

If you create a Graphics object from a bitmap, it will draw on this bitmap, not on your user interface. Instead, use the Graphics object from the PaintEventArgs e of your OnPaint method, to draw directly on the form or a control.

e.Graphics.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);

You should never create your own Graphics object.

Create your own grid control:

public class GridPanel : Panel
{
    public GridPanel()
    {
        DoubleBuffered = true; // Speeds up drawing, e.g. when panel is resized.

        // Set default colors
        BackColor = Color.Black;
        ForeColor = Color.Green;
    }

    private int _lenghtBetweenGridPoints = 20;
    public int LenghtBetweenGridPoints
    {
        get { return _lenghtBetweenGridPoints; }
        set {
            if (value != _lenghtBetweenGridPoints) {
                _lenghtBetweenGridPoints = value;
                Invalidate(); // Redraw the grid.
            }
        }
    }

    private int _sizeGridPoints = 3;
    public int SizeGridPoints
    {
        get {
            return _sizeGridPoints;
        }
        set {
            if (value != _sizeGridPoints) {
                _sizeGridPoints = value;
                Invalidate(); // Redraw the grid.
            }
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // e.Graphics.Clear(Color.Black); Not necessary. We use the BackColor of the panel.
        if (LenghtBetweenGridPoints > 0 && SizeGridPoints > 0) {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // Optional.
            using (var brush = new SolidBrush(ForeColor)) { // We use the ForeColor of the panel.
                for (int x = LenghtBetweenGridPoints; x < Width; x += LenghtBetweenGridPoints) {
                    for (int y = LenghtBetweenGridPoints; y < Height; y += LenghtBetweenGridPoints) {
                        e.Graphics.FillEllipse(brush, x, y, SizeGridPoints, SizeGridPoints);
                    }
                }
            }
        }
    }
}

Once it has been compiled, it will automatically appear in toolbox window and you can drag and drop it on your form. You will even be able to edit the properties LenghtBetweenGridPoints and SizeGridPoints in the properties window.

You could also simply use the already available BackColor and ForeColor properties of the panel for the grid. This would allow you to set the colors in the properties window as well. Don't forget to dispose brushes that you have created.


Important: Do not call OnPaint directly. Instead, call the Invalidate or Refresh methods of the object you want to redraw. The point is that Windows decides when to call OnPaint. E.g. if Invalidate is called too frequently (e.g. 5 times in 1/60 seconds), Windows might decide to not call OnPaint every time, as this would create lag. On the other hand, when the user resizes the panel, Windows will call OnPaint automatically. If you restore a window that was minimized, this will re-paint the control as well. Otherwise it would remain black.

Upvotes: 1

Related Questions