Как ждать, пока onPaint закончит рисовать (C #) - PullRequest
2 голосов
/ 02 июня 2011

Привет в зависимости от темы: Как динамически создать изображение jpg в памяти с помощью .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;

Но это не решает проблему

---------------------- обновление ------------------

 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 ]

3 голосов
/ 02 июня 2011

Все обработчики событий выполняются в главном потоке приложения, поэтому невозможно, чтобы метод для обработки события был запущен до завершения метода, который обрабатывает предыдущее событие.это не из-за перекрывающихся обработчиков событий.

1 голос
/ 02 июня 2011

, чтобы избежать мерцания самокрашенных элементов управления, вы можете использовать DoubleBuffer для рисования формы / элемента управления.Добавьте это к конструктору:

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

некоторые методы защиты от мерцания

1 голос
/ 02 июня 2011

Вы можете попробовать переопределить метод 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);
   }
}
...