2010-06-18 29 views
5

Tôi đang cố thực hiện phương pháp sau: void Ball :: DrawOn (Graphics g);Đệm đôi C#

Phương pháp nên vẽ tất cả các vị trí trước đó (được lưu trữ trong hàng đợi) của quả bóng và cuối cùng là vị trí hiện tại. Tôi không biết nếu có vấn đề, nhưng tôi in các địa điểm trước đó bằng cách sử dụng g.DrawEllipse (...) và vị trí hiện tại bằng cách sử dụng g.FillEllipse (...).

Câu hỏi đặt ra là, như bạn có thể tưởng tượng có rất nhiều bản vẽ cần thực hiện và do đó màn hình bắt đầu nhấp nháy nhiều. Tôi đã tìm kiếm một cách để tăng gấp đôi bộ đệm, nhưng tất cả những gì tôi có thể tìm thấy là 2 cách sau:

1) System.Windows.Forms.Control.DoubleBuffered = true;

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

trong khi cố gắng sử dụng giá trị đầu tiên, tôi nhận được lỗi giải thích rằng từ trong phương thức này, Thuộc tính DoubleBuffered không thể truy cập được do mức độ bảo vệ của nó. Trong khi tôi không thể tìm cách sử dụng phương thức SetStyle.

Hoàn toàn có thể tăng gấp đôi bộ đệm trong khi tất cả quyền truy cập Tôi có là đối tượng đồ họa tôi nhận làm đầu vào trong phương pháp không?

Cảm ơn trước,

Edit: tôi đã tạo ra lớp sau

namespace doubleBuffer 
{ 
    class BufferedBall : System.Windows.Forms.Form{ 
     private Ball ball; 
     public BufferedBall(Ball ball) 
     { 
      this.ball = ball; 
     } 

    public void DrawOn(Graphics g){ 
     this.DoubleBuffered = true; 
     int num = 0; 
     Rectangle drawArea1 = new Rectangle(5, 35, 30, 100); 
     LinearGradientBrush linearBrush1 = 
     new LinearGradientBrush(drawArea1, Color.Green, Color.Orange, LinearGradientMode.Horizontal); 
     Rectangle drawArea2 = new Rectangle(5, 35, 30, 100); 
     LinearGradientBrush linearBrush2 = 
      new LinearGradientBrush(drawArea2, Color.Black, Color.Red, LinearGradientMode.Vertical); 
     foreach (PointD point in ball.previousLocations) 
     { 
      Pen myPen1; 
      if (num % 3 == 0) 
       myPen1 = new Pen(Color.Yellow, 1F); 
      else if (num % 3 == 1) 
       myPen1 = new Pen(Color.Green, 2F); 
      else 
       myPen1 = new Pen(Color.Red, 3F); 
      num++; 
      myPen1.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid; 
      myPen1.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; 
      myPen1.EndCap = System.Drawing.Drawing2D.LineCap.AnchorMask; 
      g.DrawEllipse(myPen1, (float)(point.X - ball.radius), (float)(point.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius)); 
     } 
     if ((ball.Host.ElapsedTime * ball.Host.FPS * 10) % 2 == 0){ 
      g.FillEllipse(linearBrush1, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius)); 
     }else{ 
      g.FillEllipse(linearBrush2, (float)(ball.Location.X - ball.radius), (float)(ball.Location.Y + ball.radius), (float)(2 * ball.radius), (float)(2 * ball.radius)); 
     } 
    } 
} 

}

và bóng drawOn trông như thế này:

new BufferedBall(this).DrawOn(g); 

Là Ý của bạn là gì? bởi vì nó vẫn còn nhấp nháy?

+0

Vâng, cách SetStyle() là chính xác và bạn đang thực hiện chính xác. AFAIK, thuộc tính DoubleBuffered không được sử dụng (SetStyle được ưa thích), nhưng bạn luôn có thể phân lớp Control/Form/bất cứ điều gì và sử dụng nó ở đó (nó được bảo vệ). – sunside

Trả lời

3

Form lớp có thuộc tính DoubleBuffered được hiển thị là được bảo vệ. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx nhưng vì bạn lấy được biểu mẫu của mình từ Form, bạn có thể sử dụng nó.

+0

Không, nó được bảo vệ. – LmSNe

+2

có, nhưng bạn đang xuất phát từ Biểu mẫu. Giống như khi bạn tạo ứng dụng winforms cơ bản, nó tạo Form1 đến từ Form. Bạn có thể truy cập nó từ đó. Nếu không - bạn luôn có thể tạo trình bao bọc hiển thị thuộc tính này. – Andrey

1

Cách đơn giản hơn để đặt kiểu đệm đôi của các lớp dẫn xuất có điều khiển là sử dụng sự phản chiếu. Xem ở đây: http://www.csharp-examples.net/set-doublebuffered/

Điều đó sẽ giúp bạn tiết kiệm được bước phân lớp kiểm soát chỉ để đặt thuộc tính được bảo vệ.

+0

Nhưng điều đó sẽ cần truy cập vào đối tượng tôi đang vẽ, phải không? Tất cả truy cập tôi có là đối tượng Đồ họa được cung cấp dưới dạng tham số cho hàm. Có thể phản ánh trong tình huống như vậy không? – LmSNe

+0

Có. Nó có thể được thực hiện thông qua sự phản chiếu chỉ với một vài dòng mã: http://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form –

2
this.DoubleBuffered = true; 

Đó là tốt nhưng bạn để di chuyển bản Tuyên Bố này để các nhà xây dựng. Bộ đệm đôi yêu cầu thiết lập, Windows Forms phải tạo bộ đệm, phải được thực hiện trước sự kiện sơn chạy. Hàm tạo là lý tưởng.

1

Bạn không cần đặt DoubleBuffered thành true mỗi khi bạn vẽ lại. Nó không bị tắt khi vẽ xong. Chỉ cần loại bỏ các dòng từ DrawOn và đặt nó trong constructor hoặc Forms Designer và kiểm tra kết quả. Đặt giá trị thành false tạo ra nhấp nháy đáng kể trong khi đặt thành true thì không.

tôi đã cố gắng mã của bạn trong một hình thức mà một bộ đếm thời buộc một vẽ lại mỗi phần nghìn giây và nhận thấy không nhấp nháy khi DoubleBuffered là đúng:

private int yDir = 1,xDir=1; 
int step = 1; 

private void timer1_Tick(object sender, EventArgs e) 
{ 
    if (ball.Location.Y >= this.Height-50) 
     yDir = -1 ; 
    if (ball.Location.X >= this.Width-50) 
     xDir= -1 ; 

    ball.MoveBy(xDir*step,yDir*step); 
    ball.Host.ElapsedTime++; 
    this.Invalidate(); 
} 

private void DoubleBufferedBall_Paint(object sender, PaintEventArgs e) 
{      
     DrawOn(e.Graphics); 
} 
0

Một lựa chọn khác, mà tôi sẽ quăng ra cho bạn, là để làm tất cả các bản vẽ của bạn vào một Bitmap, và sau đó trong phương pháp OnPaint, bạn chỉ cần vẽ Bitmap đó vào biểu mẫu.

Hướng dẫn sử dụng, nhưng nó cung cấp cho bạn toàn quyền kiểm soát. Tôi đã sử dụng nó với một số thành công trên một số dự án thú cưng của tôi.

Bạn cũng có thể muốn xem xét XNA - nó có thể là quá mức cần thiết cho dự án của bạn ở đây, nhưng bạn có thể sử dụng XNA trong WinForms làm công cụ kết xuất.

+0

Đó có phải là ý của bạn không? void công cộng DrawOn (Graphics g) { Bitmap bitmap = new Bitmap (800, 600, g); Đồ họa g1 = Graphics.FromImage (bitmap); // vẽ tới g1 ... g.DrawImage (bitmap, điểm mới (0, 0)); } Bởi vì điều này vẫn còn nhấp nháy. – LmSNe

+0

Vâng, đúng vậy, nhưng tôi không chắc tại sao nó vẫn nhấp nháy cho bạn. – Nate

Các vấn đề liên quan