2010-03-04 67 views
22

在C#WinForms中 - 我正在繪製一個實時線形圖,它基於每500毫秒通過串行端口接收的數據。強制形式重繪?

e.Graphics.DrawLine邏輯位於窗體的OnPaint處理程序中。

一旦我從串口收到數據,我需要調用一些導致窗體重繪的事件,以便調用OnPaint處理程序。我試過這個。刷新和this.Invalidate,會發生什麼,我失去了以前在窗體上繪製的任何東西。

有沒有另一種方法來實現這一點,而不會丟失表單上繪製的內容?

回答

20

問題是您應該考慮將繪圖數據存儲在某處。如前所述,緩衝位圖是一種解決方案。但是,如果您沒有太多畫圖,有時將繪圖數據存儲在變量或數組中並重新繪製OnPaint事件中的所有內容會更容易和更好。

假設您收到一些應添加到圖表的點數據。所有的杉杉您創建一個列表:

List<Point> points = new List<Point>(); 

然後每次你得到一個新的時間點,你將它添加到列表中,並刷新表單:

points.Add(newPoint); 
this.Refresh(); 

在OnPaint事件把下面的代碼:

private void Form_Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.DrawLines(Pens.Red, points); 
} 

這個工程相當快達莫名其妙100個000點,並使用比緩衝液位內存少得多。但是你應該根據繪圖的複雜性來決定使用哪種方式。

+0

謝謝 - 效果很好。 快速問題 - 我正在實時繪製此折線圖 - 最終我將超過屏幕上的最大可用寬度,因此我希望我在表單上繪製的線稍微向左移動,以便爲正在繪製的新座標騰出空間。有關如何做到這一點的任何建議?基本上我正在開發一個簡單的EKG類型的應用程序。 – Chris 2010-03-04 06:43:24

+2

有很多方法可以做到這一點。例如,您可以使用e.Graphics.TranslateTransform(-x,0);這使得您繪製的所有圖形都向左移動x個像素。 – Zenya 2010-03-04 07:43:30

0

處理此問題的默認方法是創建一個內存位圖並在其上繪製,然後將圖片框的圖像屬性設置爲內存位圖。

5

正如重新運行所述,您需要緩衝您的表單(因爲您在繪製數據後似乎會丟棄數據)。

這基本上是我會怎麼做:

private Bitmap buffer; 

// When drawing the data: 
if (this.buffer == null) 
{ 
    this.buffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); 
} 

// then draw on buffer 
// then refresh the form 
this.Refresh(); 

protected override void OnPaint(PaintEventArgs e) 
{ 
    if (this.buffer != null) 
    { 
     e.Graphics.DrawImage(this.buffer); 
    } 
} 

這就是說,你可能想緩存數據,以便你可以改變緩衝區的大小,當窗體大小更改,然後重繪舊數據在上面。

0

您需要將歷史數據存儲在某個地方並重新繪製它。

這比緩存和裁剪位圖要容易得多。

1

的解決方案可能是this.Invalidate()