如何等待onPaint完成绘画(C#)

时间:2011-06-02 12:56:38

标签: c# gdi system.drawing

您好基于此处的主题:How to create a jpg image dynamically in memory with .NET?

我有这个方法:

        int maxVal = 50;
        int maxXCells = r.Next(maxVal);
        int maxYCells = r.Next(maxVal);
        int cellXPosition = r.Next(maxVal);
        int cellYPosition = r.Next(maxVal);
        int boxSize = 10;


        Graphics fg = this.CreateGraphics();


        using (var bmp = new System.Drawing.Bitmap(maxXCells * boxSize + 1, maxYCells * boxSize + 1))
        {


            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.Clear(Color.Yellow);
                Pen pen = new Pen(Color.Black);
                pen.Width = 1;

                //Draw red rectangle to go behind cross
                Rectangle rect = new Rectangle(boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize, boxSize);
                g.FillRectangle(new SolidBrush(Color.Red), rect);

                //Draw cross
                g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize * cellXPosition, boxSize * cellYPosition);
                g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * cellYPosition, boxSize * cellXPosition, boxSize * (cellYPosition - 1));

                //Draw horizontal lines
                for (int i = 0; i <= maxXCells; i++)
                {
                    g.DrawLine(pen, (i * boxSize), 0, i * boxSize, boxSize * maxYCells);
                }

                //Draw vertical lines            
                for (int i = 0; i <= maxYCells; i++)
                {
                    g.DrawLine(pen, 0, (i * boxSize), boxSize * maxXCells, i * boxSize);
                }
            }
            fg.DrawImage(bmp, 0, 0);
            fg.Dispose();

        }

它基于随机事件触发(可以在一秒钟内多次)。我该怎么办,只有在当前绘图完成后才能绘制新图像?目前,我可以看到,如果运行此方法的事件比绘图完成时触发得更快,则屏幕会闪烁。在上一次绘图完成之前避免绘图的常见解决方法是什么?

这是我在OnPaint方法中包含的内容:

   protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
    {
        finishedInvalidating = false;
        fg = this.CreateGraphics();
        lock (bmp)
        {
            fg.DrawImage(bmp, 0, 0);
        }
        fg.Dispose();
        finishedInvalidating = true;

但这并没有解决问题

---------------------- update ------------------

 public partial class LadderFrm : Form
{
    Bitmap bmp;

    int numCols = 3;
    int colWidth = 100;
    int numRows = 30;
    int rowHeight = 20;
    bool finishedInvalidating = false;

    decimal lastprice;

    public LadderFrm()
    {
        bmp = new System.Drawing.Bitmap(numCols * colWidth + 1, numRows * rowHeight + 1);
        prepareLadderGraphics();
    }



    // prepare initial ladder background
    private void prepareLadderGraphics()
    {

        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.Clear(Color.LightGray);
            Pen pen = new Pen(Color.Black);
            pen.Width = 1;

            // drawCells
            for (int i = 0; i < numCols; i++)
            {
                for (int j = 0; j < numRows; j++)
                {
                    Rectangle rect = new Rectangle(i * colWidth, j * rowHeight, colWidth, rowHeight);
                    g.DrawRectangle(pen, rect);
                }
            }
            g.Dispose();
        }

    }


    protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
    {
        Graphics fg = this.CreateGraphics();
        lock (fg)
        {
            lock (bmp)
            {
                fg.DrawImage(bmp, 0, 0);
            }
        }
        fg.Dispose();
    }

    public void OrderBookUpdateFn(OrderBookEvent orderBookEvent)
    {



        if (lastprice != orderBookEvent.ValuationAskPrice)
        {
            lastprice = orderBookEvent.ValuationAskPrice;
            lock (bmp)
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    Pen pen = new Pen(Color.Black);
                    pen.Width = 1;
                    for (int i = 0; i < numRows; i++)
                    {
                        Rectangle rect = new Rectangle(colWidth + 1, i*rowHeight + 1, colWidth - 1, rowHeight - 1);
                        g.FillRectangle(new SolidBrush(Color.LightGray), rect);
                        g.DrawString(lastPrice.ToString(), new Font(FontFamily.GenericSansSerif, 10), new SolidBrush(Color.Black), new Point(colWidth + 1, i*rowHeight + 1));
                    }
                    g.Dispose();
                }
                this.Invalidate(new Rectangle(0, 0, 1, 1));
            }
    }
}

上面的代码很有效,但是我不确定它是否正确。这仅用于测试目的。方法OrderBookUpdateFn(OrderBookEvent orderBookEvent)经常被触发(有时几十次)。

3 个答案:

答案 0 :(得分:3)

事件处理程序都在应用程序的主线程中运行,因此在处理上一个事件的方法完成之前,不可能启动处理事件的方法。

如果遇到闪烁,则不是因为事件处理程序重叠。

答案 1 :(得分:1)

您可以尝试重写OnPaint方法,调用base.OnPaint();然后再做手工绘画。

protected override void OnPaint(PaintEventArgs e)
{
   // call base
   base.OnPaint(e);

   // Do your stuff after the rest has been painted
   if(this.picture != null && this.pictureLocation != Point.Empty)
   {
      e.Graphics.DrawImage(this.picture, this.pictureLocation);
   }
}

答案 2 :(得分:1)

为了避免自绘控件的闪烁,你可以DoubleBuffer表单/控件的绘图。 将其添加到构造函数:

this.SetStyle(
  ControlStyles.AllPaintingInWmPaint |
  ControlStyles.UserPaint |
  ControlStyles.DoubleBuffer,true);

some anti-flicker techniques