2017-09-02 96 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