2009-07-19 3 views
1

Я пытаюсь создать графику движения слайдера. Код лучше объясняет это.рисунок Ошибка производительности графики

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Drawing.Drawing2D; 

namespace temp 
{ 

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 
     private System.Drawing.Graphics g; 
     private System.Drawing.Pen pen1 = new System.Drawing.Pen(Color.Black, 1F); 

     //timer for animation 
     private void Form1_Load(object sender, EventArgs e) 
     { 
      Timer a = new Timer(); 
      a.Interval = 60; 
      a.Tick += new EventHandler(a_Tick); 
      a.Start(); 
     } 

     void a_Tick(object sender, EventArgs e) 
     { 
      button1_Click(this, null); 

     } 

     //draws randomly generated point array. 
     int cnt = 0; 
     private void button1_Click(object sender, EventArgs e) 
     { 
      rAr(); 
      g = pictureBox1.CreateGraphics(); 

      g.Clear(Color.Violet); 
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
      g.SmoothingMode = SmoothingMode.HighQuality; 
      g.DrawCurve(pen1, points2); 
      cnt++; 
     } 

     Random r = new Random(); 
     Point[] p = new Point[100]; 
     Point[] points2 = new Point[100]; 
     int c = 4; 
     //fills new random point array 
     private void rAr() 
     { 
      points2.CopyTo(p, 0); 
      int cc = 1; 
      for (int i = points2.Length - 1; i > 0; i--) 
      { 
       points2[i - 1] = new Point(100 - cc, p[i].Y); 
       cc++; 
      } 
      points2[99] = new Point(100, r.Next(1, 50)); 
     } 

    } 
} 

Этот код отлично работает, проблема заключается в том, что требуется много CPU и автоматизация не очень гладкая. есть ли другой способ добиться того же, что и с гораздо меньшим объемом процессора. Спасибо за повторы

+0

Помимо того, что вы не располагаете графическим объектом и несколько нечетной конструкцией с таймером, вызывающим обработчик события button_click, я действительно не вижу проблемы. Программа потребляет менее 1% процессора на моем ноутбуке. –

ответ

7

(недоношенные) Оптимизации

В дополнение к другим ответы уже отправлены, вы пытаетесь провести кривую сплайна через 100 пунктов.

Это, вероятно, плохая идея по двум причинам: во-первых, подгонка кривой до 100 баллов не является особенно быстрой задачей при любых обстоятельствах. Во-вторых, поскольку точки все на расстоянии 1 пиксель, вероятно, нет никакой визуальной выгоды для использования кривой.

Таким образом, есть еще несколько вещей, которые вы могли бы сделать, что может улучшить скорость:

  • Попробуйте использовать PolyLine, а не кривой,

  • Если вам нужно использовать кривую, то вам, вероятно, не нужно использовать 100 точек на 100 пикселей чертежа. Использование 10 или 20 позиций по этой ширине может дать вам лучшие результаты и значительно сократить работу по подгонке кривой, которая должна выполняться .net.

  • Вы также можете удалить некоторые промежуточные точки, которые лежат на линии/кривой, так что у вас будет меньше линий для рисования. например если у вас есть точки в (10,57) (11, 57) (12,57), вы можете сбросить среднюю точку и просто провести прямую линию от (10,57) до (12,57).

Неверный алгоритм?

Но подождите! Прежде чем вы оптимизируете код - это действительно решение проблемы?

Звучит так, как будто содержание не предназначено для «изменения», а просто прокручивается вбок. В этом случае только новые пиксели, введенные с одной стороны изображения, фактически «изменяются» с каждым кадром - остальные просто перемещаются вбок. В этом случае вы можете прокручивать (перемещать) область изображения, содержащую «старое» изображение кривой, а затем просто нарисовать дополнительный пиксель или два, которые «прокручиваются». Прокрутка таким образом может быть достигнута несколькими способами (например, blitting в графике или если содержимое всего окна прокручивается, используя команды прокрутки Windows Form)

Точно так же, если данные не являются но просто «прокрутка», то перестройка массива для каждого кадра излишне дорога. Используя круговой буфер, вы можете просто добавить новую точку в «конец» массива и удалить ее с самого начала без необходимости перераспределять массив или копировать все промежуточные точки вообще.

Итак, все дело в использовании подходящего инструмента для работы.

3

Вы должны переместить все графического кода в Button1 в случае краски вашего PictureBox в, что-то вроде этого:

private void button1_Click(object sender, EventArgs e) 
    { 
     rAr(); 
     pictureBox1.Invalidate(); 
     cnt++; 
    } 

private void picturebox1_Paint(object sender PaintEventArgs e) 
{ 
    using graphics g = e.Graphics() 
    { 
      g.Clear(Color.Violet); 
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
      g.SmoothingMode = SmoothingMode.HighQuality; 
      g.DrawCurve(pen1, points2); 

    } 
} 
+2

Это призыв к CreateGraphics(), который убивает вас. Предположение Энди - путь, потому что создание нового объекта Graphics каждый раз дорого. Вы можете сделать еще один шаг и инкапсулировать все это в UserControl и переопределить метод OnPaint usercontrol для пары менее вызовов стека. Кроме того, вы должны установить стиль управления или стиль форм для DoubleBuffering для меньшего количества мерцания. –

+0

Вы также можете рассмотреть возможность переписывания вашей функции rAr (по крайней мере, если вы будете использовать больше точек или меньших интервалов позже) и улучшите ее f.e. используя ringbuffer, но это может не стоить того - drawCurve, возможно, ест гораздо больше циклов процессора. – schnaader

Смежные вопросы