2017-09-02 276 views
1

我正在使用眼動儀在窗體上顯示眼球運動。這些動作一直閃爍很多,所以我發現我可以使用BufferedGraphics,除了眼動開始之外,它們都可以正常工作,它將窗體從原始顏色變成黑色。這是代碼。希望有人能幫助!爲什麼渲染車削黑色

private void button2_Click(object sender, EventArgs e) 
{ 
    var host = new Host(); 
    var gazeStream = host.Streams.CreateGazePointDataStream(); 
    gazeStream.GazePoint((x, y, ts) 
     => drawCircle(new PointF((float)x, (float)y))); 
} 

delegate void SetCallback(PointF point); 

private void drawCircle(PointF point) 
{ 
    float x = point.X; 
    float y = point.Y; 

    if (this.InvokeRequired) 
    { 
     SetCallback d = new SetCallback(drawCircle); 
     this.Invoke(d, new object[] { point }); 
    } 
    else 
    { 
     SolidBrush semiTransBrush = new SolidBrush(Color.Coral); 
     Pen pen = new Pen(Color.Aquamarine, 2); 

     BufferedGraphicsContext currentContext; 
     BufferedGraphics myBuffer; 
     // Gets a reference to the current BufferedGraphicsContext 
     currentContext = BufferedGraphicsManager.Current; 
     // Creates a BufferedGraphics instance associated with Form1, and with 
     // dimensions the same size as the drawing surface of Form1. 
     myBuffer = currentContext.Allocate(this.CreateGraphics(),this.DisplayRectangle); 
     myBuffer.Graphics.DrawEllipse(pen, x, y, 100, 100); 
     myBuffer.Graphics.FillEllipse(semiTransBrush, x, y, 100, 100); 


     // Renders the contents of the buffer to the specified drawing surface. 
     myBuffer.Render(this.CreateGraphics()); 

     myBuffer.Dispose(); 
    } 

enter image description here

您可以在圖片中看到的圓圈顯示控件後面這似乎是形式沒有了嗎?

+0

嘗試'myBuffer.Graphics.Clear(this.BackColor);'繪製形狀之前 - 也就是如果你沒有別的形式 –

+0

我有單選按鈕,並在窗體上的標籤上。控件仍然顯示。它看起來幾乎像表單的背景已被刪除,而不是僅僅改變顏色 – user8370201

+0

問題的代碼在哪裏?顯示更多關於方法的詳細信息 –

回答

1

當您分配緩衝區時,它會使用您提供的圖形創建兼容的渲染表面。但它不會複製它或任何東西,所以如果你只畫一個圓圈,其餘部分仍然是黑色的。

BufferedGraphics真的可以幫助您避免在特殊情況下閃爍(例如,系統雙緩衝由於某種原因必須被禁用),但這裏這是一個矯枉過正。

所以關鍵只是啓用雙緩衝,並在Paint事件(或OnPaint方法)中執行每個繪製。在你的代碼中,你會立即進行繪製,它總是閃爍。相反,您應該使表單失效,並讓系統執行定期重繪會話,如果您願意,可以使用雙重緩衝。

到構造函數:

SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 

然後修改Click事件:

private PointF lastGazePoint; 

private void button2_Click(object sender, EventArgs e) 
{ 
    var host = new Host(); 
    var gazeStream = host.Streams.CreateGazePointDataStream(); 
    gazeStream.GazePoint((x, y, ts) => 
     { 
      lastGazePoint = new PointF((float)x, (float)y); 
      Invalidate(); 
     }); 
} 

繪畫本身:

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 
    DrawCircle(e.Graphics, lastGazePoint.X, lastGazePoint.Y); 
} 

最後,修改DrawCircle使用來自PaintEventArgsGraphics

private void DrawCircle(Graphics g, float x, float y) 
{ 
    using (Brush semiTransBrush = new SolidBrush(Color.Coral)) 
    { 
     using (Pen pen = new Pen(Color.Aquamarine, 2)) 
     { 
      g.DrawEllipse(pen, x, y, 100, 100); 
      g.FillEllipse(semiTransBrush, x, y, 100, 100); 
     }   
    }   
} 
+0

謝謝你的工作。只需要弄清楚如何保持圓圈移動,如果用戶遠離屏幕並再次回到屏幕 – user8370201

+0

您好我正在嘗試使用相同的邏輯來播放xml文件中的圓圈運動。我能夠讀取文件並解析它以獲取x和y,但圓圈只會繪製一次。我使用了相同的繪製圓和onPaint方法,但是這次我有另一種方法檢索座標public void EyeMove(float x,float y) {Point = new PointF(x,y); } – user8370201

+0

你應該提供一些細節。如果沒有源代碼,我可以懷疑你在播放動畫時阻止了UI線程,而只會看到最後一幀。重播引擎不應該包含'Thread.Sleep'或類似的線程阻塞技術。如果沒有足夠的信息,只需發佈​​另一個問題的詳細信息。 – taffer