【问题标题】:C# Drawing - best solutionC# 绘图 - 最佳解决方案
【发布时间】:2012-07-09 20:59:55
【问题描述】:

今天,当我在上面画画时,我正在尝试解决闪烁面板的问题。

我读过很多帖子,比如这些:

所以我尝试使用 doubleBuffered 在 PictureBox、MyPanel 上绘图,但是当我阅读时发现的最佳解决方案是,我不能每次都使用 g.Clear(),之后即使在非 doubleBuffered 面板上也是如此,闪烁消失了。

我什至读到,我应该在绘制完成后释放图形。所以我到处使用(Graphics g = panel.CreateGraphics())。

所以我的问题,仅当我在位图上绘制一些东西时才为位图创建图形是个好主意吗?因为在我创建 Bitmap 和 Graphics 之前(只针对这个位图,不是针对所有组件),所以我每次都有这个位图可用的 Graphics

这是我的代码:

public void newSizeDrawing()
    {
        Size size = collector.getLetterSize(selectedName);
        Size drawingSize = new Size(size.Width * (pixelSizeArray[pixelSize] + 1),size.Height * (pixelSizeArray[pixelSize] + 1));
        bitmapDraw = new Bitmap(drawingSize.Width, drawingSize.Height);
        int width = (this.MinimumSize.Width - panelDraw.MinimumSize.Width) + drawingSize.Width + 10;
        int height = (this.MinimumSize.Height - panelDraw.MinimumSize.Height) + drawingSize.Height + 10;
        this.Size = new Size(
            (width > this.MinimumSize.Width) ? width : this.MinimumSize.Width,
            (height > this.MinimumSize.Height) ? height : this.MinimumSize.Height);
        zeroDrawPosition = new Point((panelDraw.Size.Width - bitmapDraw.Width) / 2 - 1, (panelDraw.Size.Height - bitmapDraw.Height) / 2 - 1);
        using (Graphics g = panelDraw.CreateGraphics())
        {
            g.Clear(panelDraw.BackColor);
        }
        redrawDrawingLetter();
    }
public void redrawDrawingLetter()
    {
        bool[][] grid = collector.getArray(selectedName);
        using (Graphics graphicDraw = Graphics.FromImage(bitmapDraw))
        {
            graphicDraw.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
            graphicDraw.Clear(panelDraw.BackColor);
            int pxSize = pixelSizeArray[pixelSize];
            for (int y = 0; y < grid.Length; y++)
            {
                for (int x = 0; x < grid[y].Length; x++)
                {
                    graphicDraw.FillRectangle((grid[y][x] ? Brushes.Black : Brushes.White), x * (pxSize + 1), y * (pxSize + 1), pxSize, pxSize);
                }
            }
        }
        redrawDrawingPanel();
    }
private void redrawDrawingPanel()
    {
        using (Graphics g = panelDraw.CreateGraphics())
        {
            if (bitmapDraw != null)
                g.DrawImage(bitmapDraw, zeroDrawPosition);
        }
    }
private void panelDraw_Paint(object sender, PaintEventArgs e)
    {
        redrawDrawingPanel();
    }

没有人可以向我解释如何以最好的方式在 C# 中绘图。所以也许我的代码不好,但这就是我问如何正确执行它的原因。

newSizeDrawing 仅由我自己调用,当用户点击 +- 按钮时。如果像素打开或关闭,我有 bool 二维数组。这是为微芯片和LED显示屏绘制字母的程序(通常是8px的字母高度)。

我写了一个方法来检查鼠标是否从一个“像素”移动到另一个,所以我不会在每次调用 mouseMove 事件后重新绘制它,因为“像素”可以从 10x10 像素到 30x30 像素。

【问题讨论】:

  • 嗨 Arxeiss,你有什么代码可以说明你在做什么吗?通过一些代码示例,人们可以查看您在做什么,并提出改进建议或同意您实施的内容 - 分享想法也更容易!
  • 不要使用 CreateGraphics(),双缓冲只能在使用 Paint 事件时起作用。并且在您的事件处理程序中处置 e.Graphics 对象,您没有创建它。
  • 我在第一个帖子中添加了代码。因为我没有双缓冲面板,我仍然可以使用 CreateGraphics,不是吗?但感谢您的解释。

标签: c# .net drawing panel


【解决方案1】:
private void panelDraw_Paint(object sender, PaintEventArgs e)
{
    redrawDrawingPanel();
}

这是根本错误的。 Paint 事件通过 e.Graphics 让您绘制您想要绘制的任何内容。当您打开双缓冲时,e.Graphics 引用位图,它使用 BackColor 进行初始化。然后,您继续使用从 CreateGraphics() 获得的 另一个 图形对象进行绘图。那个直接画到屏幕上。

非常发音时你看到的闪烁效果。一瞬间,您会看到其他 Graphics 上下文绘制的内容。然后您的 panelDraw_Paint() 方法返回并且 Winforms 绘制双缓冲位图。上面什么都没有,所以它会立即抹掉你画的东西。

修改redrawDrawingPanel() 方法并为其提供一个Graphics 类型的参数。在调用中传递 e.Graphics。并且只使用该图形对象,删除对 CreateGraphics() 的所有调用。

【讨论】:

  • 我现在有点困惑。如果我不能使用 CreateGraphics(),当 Panel 调整大小时我应该在哪里使用 g.Clear()? (面板有 Anchor Top、Left、Bottom、Right,只有通过程序我才能调整表格的大小,正如您在 public void newSizeDrawing() 中看到的那样?还有立即重绘的功能呢,因为我知道有些想法被改变了?我应该怎么做这个,如果我不能使用 CreateGraphics()?谢谢
  • 在构造函数中设置 ResizeRedraw = true 以便在面板调整大小时触发绘制。当您知道发生了变化时使用 Invalidate()。
  • 在哪个构造器中?我不使用自己的面板。但是 Ivalidate 很棒,每次调整大小时我都可以调用它,因为我这样写,你只能通过按钮调整大小。所以对我来说已经足够了。非常感谢
  • 我现在尝试删除所有 CreateGraphics 和所有 Clear(),仅在 Paint 事件中绘制,它的效果非常好 :) 非常感谢但最后一件事,我必须使用 Graphics.FromImage() 来绘制位图,稍后我在Paint 事件中将其绘制到Panel。或者我可以通过其他方式做到这一点?我使用Bitmap,因为Panel需要重绘后,我不必绘制整个图像,因为它在Bitmap中。它是否正确?非常感谢
猜你喜欢
  • 2020-04-12
  • 2023-03-13
  • 1970-01-01
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多