2015-08-07 4 views
2

Попытка отображения графика в приложении формы. Создал элемент управления PictureBox и инициализировал этот класс своим значением. При изменении размера график всегда обновляется; на мышином прокрутке это вряд ли получится. Это элемент управления GraphBox, PictureBox внутри GraphBoxPanel, панель управления.PictureBox обновляется только при изменении размера

Этот класс:

public struct DLT_measure_item 
{ 
    public DateTime ts; 
    public float value; 
    public int id; 
    public int X; 
    public int Y; 
} 
[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct dlt_ser_meas 
{ 
    public byte msg_id;   // 'D' 
    public byte meas_count;  // Number of measures 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public byte[] port;  // Module ID (4b) + Port ID (4b) 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public float[] meas;  // measure 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 
    public byte[] msg_end; 
} 

public class manageGraph 
{ 
    private PictureBox box; 
    public bool displayGrid = true; 
    private int horAxisMin_p = 0; 
    private int horAxisMax_p = 300; 
    private float verAxisMin_p = 0; 
    private float verAxisMax_p = 40; 
    public int horAxisMin 
    { 
     get { return this.horAxisMin_p; } 
     set 
     { 
      if (value < horAxisMax_p) 
      { 
       this.horAxisMin_p = value; 
       reDraw(); 
      } 
     } 
    } 
    public int horAxisMax  
    { 
     get { return this.horAxisMax_p; } 
     set 
     { 
      if (value > horAxisMin_p) 
      { 
       this.horAxisMax_p = value; 
       reDraw(); 
      } 
     } 
    } 
    public float verAxisMin 
    { 
     get { return this.verAxisMin_p; } 
     set 
     { 
      if (value < verAxisMax_p) 
      { 
       this.verAxisMin_p = value; 
       verPointPerUnit = graphArea.Height/(verAxisMax_p - this.verAxisMin_p); 
      } 
     } 
    } 
    public float verAxisMax 
    { 
     get { return this.verAxisMax_p; } 
     set 
     { 
      if (value > verAxisMin_p) 
      { 
       this.verAxisMax_p = value; 
       verPointPerUnit = graphArea.Height/(this.verAxisMax_p - verAxisMin_p); 
      } 
     } 
    } 
    Pen axes = new Pen(Color.Black, (float)1.5); 
    public int horAxisSpacing = 30; 
    public int verAxisSpacing = 20; 
    public int horAxis = 20; 
    public int verAxis = 20; 
    private float horPointPerUnit = 1; 
    private float verPointPerUnit = 1; 
    public int horAxisTickLen = 5; 
    public int verAxisTickLen = 5; 
    public bool horAxisShowTime = false; 
    private Rectangle graphArea = new Rectangle(); 


    public void reDraw() 
    { 
     box.Image.Dispose(); 
     Bitmap GraphBlankImage = new Bitmap(box.Width, box.Height); 
     box.Image = GraphBlankImage; 
     updatePointPerUnit(); 
     drawGrid(); 
     box.Refresh(); 

    } 
    public manageGraph(PictureBox targetImageBoxbox) 
    { 
     box = targetImageBoxbox; 
     horAxisMin_p = 0; 
     horAxisMax_p = 300; 
     verAxisMin_p = 0F; 
     verAxisMax_p = 50F; 
     updatePointPerUnit(); 
    } 
    private Point measToPoint(DLT_measure_item measure) { 
     Point coords = new Point(); 
     coords.X = graphArea.Width - (int)( 
     ((DateTime.Now - measure.ts).TotalSeconds + horAxisMin_p) * horPointPerUnit ) ; 
     coords.Y = graphArea.Height - (int)(
     ((measure.value - verAxisMin_p) * verPointPerUnit)); 
     return coords; 
    } 
    public manageGraph(PictureBox targetImageBoxbox, 
         int xmin, int xmax, float ymin, float ymax) 
    { 
     box = targetImageBoxbox; 
     horAxisMin_p = xmin; 
     horAxisMax_p = xmax; 
     verAxisMin_p = ymin; 
     verAxisMax_p = ymax; 
     updatePointPerUnit(); 
    } 

    private void updateGraphArea() 
    { 
     graphArea = new Rectangle(0, 0, box.Width - horAxis, box.Height - verAxis); 
    } 

    private void updatePointPerUnit() 
    { 
     updateGraphArea(); 
     horPointPerUnit = graphArea.Width/(horAxisMax_p - horAxisMin_p); 
     verPointPerUnit = graphArea.Height/(verAxisMax_p - verAxisMin_p); 
    } 

    public void drawGrid() 
    { 

     //updatePointPerUnit(); 
     using (Graphics g = Graphics.FromImage(box.Image)) 
     { 
      // X axis 
      g.DrawLine(axes, graphArea.Left, graphArea.Bottom, box.Width, graphArea.Bottom); 
      // Y axis 
      g.DrawLine(axes, graphArea.Right + 1, graphArea.Top, graphArea.Right +1, graphArea.Bottom); 
      using (Font ArialFont = new Font("Arial", 10)) 
      { 
       g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 
       // Put x labels 
       for (int i = 1; i <= (graphArea.Width/horPointPerUnit); i = i + (int)(horAxisSpacing/horPointPerUnit) + 1) 
       { 
        g.DrawString((i).ToString(), ArialFont, Brushes.Black, graphArea.Width - (i * horPointPerUnit) - 5, graphArea.Bottom +5); 
        g.DrawLine(axes, graphArea.Width - (i * horPointPerUnit), graphArea.Bottom + (horAxisTickLen/2), graphArea.Width - (i * horPointPerUnit), graphArea.Bottom - (horAxisTickLen/2)); 
       } 
       // Put y labels 
       for (int i = 1; i <= (graphArea.Height/verPointPerUnit); i = i + (int)(verAxisSpacing/verPointPerUnit) +1) 
       { 
        g.DrawString((i).ToString(), ArialFont, Brushes.Black, graphArea.Right + 1 , graphArea.Height - (i * verPointPerUnit) - 8); 
        g.DrawLine(axes, graphArea.Width - (verAxisTickLen/2), (i * verPointPerUnit), graphArea.Width + (verAxisTickLen/2), (i * verPointPerUnit)); 
       } 
      } 
      /*Put some random data*/ 
      DLT_measure_item testmeas = new DLT_measure_item(); 
      Point testGraphPoint = new Point(); 
      testmeas.ts = DateTime.Now; 
      testmeas.value = 0; 
      testGraphPoint = measToPoint(testmeas); 
      g.FillEllipse(Brushes.Blue, testGraphPoint.X, testGraphPoint.Y, 4, 4); 
      for (double i = 0; i < 300; i++) 
      { 
       double x = i; 
       double freq = 10; 
       double y = 30 - (i/10); 
       testmeas.value = (float)y; 
       testmeas.ts = DateTime.Now.AddSeconds(-1 * i); 
       testGraphPoint = measToPoint(testmeas); 
       g.FillEllipse(Brushes.Red, testGraphPoint.X, testGraphPoint.Y, 2,2); 
      } 
     } 
    } 
} 

инициализацию:

public DLThermalogMainForm() 
    { 
     InitializeComponent(); 
     Bitmap GraphBlankImage = new Bitmap(GraphBox.Width, GraphBox.Height); 
     GraphBox.Image = GraphBlankImage; 
     myGraph = new manageGraph(GraphBox); 
     myGraph.drawGrid(); 

    } 

Те обработчики:

private void Form1_ResizeEnd(object sender, EventArgs e) 
    { 
     myGraph.reDraw(); 
     OutputTextBox.AppendText("Resize." + Environment.NewLine); 
    } 

    private void GraphBox_MouseMove(object sender, MouseEventArgs e) 
    { 
     //Get the focus to have the wheel working 
     GraphBoxPanel.Focus(); 
    } 

    private void GraphBoxPanel_MouseWheel(object sender, MouseEventArgs e) 
    { 
     // Change x axis max value to zoom in/out the graph 
     myGraph.horAxisMax += e.Delta/ 120; 
     myGraph.reDraw(); 
    } 

На событие изменения размера, он всегда перерисовывает; на колесике мыши это происходит быстро только с небольшими значениями horAxisMax (это имеет смысл?), но для увеличения требуется много секунд, чтобы обновить или совсем нет. Большое спасибо

+0

Вам необходимо повторно назначить измененное изображение после манипулирования им в DrawHGrid! – TaW

+0

На самом деле я не меняю изображение, но создаю графику из изображения - должно быть, этого достаточно? И еще, я всегда избавляюсь от старого изображения, прежде чем регенерировать новый. – SimoneApprendista

+0

_I не меняю изображение, но создаю Graphics from the image_ No. A Графика не __конфигурирует любую графику; это инструмент для изменения связанного растрового изображения. Вы должны создать растровое изображение в DrawGrid и назначить его там, где будет новый box.Image также ... или передать его, а затем выполнить назначение. – TaW

ответ

1

Изменение reDraw так:

public void reDraw() 
{ 
    box.Image.Dispose(); 
    Bitmap GraphBlankImage = new Bitmap(box.ClientSize.Width, box.ClientSize.Height); 
    updatePointPerUnit(); 
    drawGrid(GraphBlankImage); 
    box.Image = GraphBlankImage; 
} 

и drawGrid так:

public void drawGrid(Bitmap bmp) 
{ 
    //updatePointPerUnit(); //?? 
    using (Graphics g = Graphics.FromImage(bmp)) 
    { 
    ... 
    ... 
    ... 
    } 
} 

Теперь Bitmap с сеткой должны немедленно отображаться в PictureBox.

Как уже упоминалось, объект Graphics является инструментом для изменения связанного Bitmap. Чтобы поднять его, Bitmap следует присвоить PictureBoxeImage.

Также обратите внимание, что если ваш PictureBox не Border, есть небольшая разница между внешней размером (он же Bounds) и внутреннего размером, ClientRectangle/ClientSize. Изображение должно иметь ClientSize

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

Но, глядя глубже в source code мы находим причину:

Изображение The PictureBox является собственностью и в его сеттера есть призыв к InstallNewImage:

public Image Image { 
     get { 
      return image; 
     } 
     set { 
      InstallNewImage(value, ImageInstallationType.DirectlySpecified); 
     } 
    } 

Тот же вызов также в нескольких других местах, как Load или в сеттер ImageLocation. Но изменение изображения только за сценой не заставит PictureBox выполнить этот вызов. A Refresh() также должен это сделать .. И, как вы узнали, изменение размера также приведет к тому, что PictureBox заберет измененные данные в растровом изображении.

+0

спасибо! Первая попытка работы! – SimoneApprendista

0

Самый простой способ принудительного обновления - это просто invalidate the control.

timer = new Timer(); 
timer.Interval = 200; //refreshes every 200 ms 
timer.Tick += (sender,e) => targetImageBoxbox.Invalidate(); 
timer.Start(); 
+0

попробовал раньше, и попробовал еще раз - нечего делать. – SimoneApprendista

+0

Я буду тестировать его дома. –

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