为什么图形没有绘制到面板上

How come the graphics is not drawing onto the panel

我想在我的面板中绘制一个网格。我用位图创建的图形对象(屏幕)没有在我的面板中绘制。我尝试调试以查看屏幕是否未绘制,但事实并非如此。

我尝试从面板 createGraphic 方法创建图形对象,并从面板绘制方法创建参数 painteventargs。两次我用它用OnPaint画它都花了太长时间。

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);
        }
    }
}

如果您从位图创建 Graphics 对象,它将在该位图上绘制,而不是在您的用户界面上绘制。相反,使用 OnPaint 方法的 PaintEventArgs e 中的 Graphics 对象直接在窗体或控件上绘制。

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

您永远不应该创建自己的 Graphics 对象。

创建您自己的网格控件:

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);
                    }
                }
            }
        }
    }
}

编译完成后,它会自动出现在工具箱中window,您可以将其拖放到表单中。您甚至可以在属性 window.

中编辑属性 LenghtBetweenGridPointsSizeGridPoints

您也可以简单地使用网格面板的已有 BackColorForeColor 属性。这也允许您在属性 window 中设置颜色。不要忘记处理您创建的画笔。


重要提示:不要直接调用 OnPaint。相反,调用要重绘的对象的 InvalidateRefresh 方法。重点是 Windows 决定何时调用 OnPaint。例如。如果 Invalidate 被调用得太频繁(例如 1/60 秒内调用 5 次),Windows 可能会决定不每次都调用 OnPaint,因为这会造成延迟。另一方面,当用户调整面板大小时,Windows 将自动调用 OnPaint。如果恢复最小化的 window,这也会重新绘制控件。否则它会保持黑色。