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

本文关键字:绘制 onPaint 等待 何等待 | 更新日期: 2023-09-27 17:58:19

Hi基于这里的线程:如何使用.NET在内存中动态创建jpg图像?

我有这样的方法:

        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;

但这并不能解决的问题

----------------------更新------------------

 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)经常被激发(有时每秒数十次)。

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

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

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

为了避免自绘制控件的闪烁,您可以对窗体/控件的绘图进行DoubleBuffer。将其添加到构造函数:

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

的一些防闪烁技术

您可以尝试重写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);
   }
}