我正在尝试创建一个简单的Windows窗体图形应用程序,每次用户点击并扩展时,基本上会绘制一个圆圈,同时慢慢消失。
当我尝试将Paint()
事件用于我的图形功能时,没有任何反应,因此我创建了一个名为“Render”的单独函数,该函数在我的主要更新Timer
中调用。
该应用程序工作但图形闪烁。经过一些研究后,我意识到我必须启用双缓冲,以便渲染到缓冲区,然后缓冲区将呈现在屏幕上。
闪烁仍然没有停止!
这是因为双缓冲仅适用于Paint()
事件,如果是,我如何才能使Paint()
事件起作用,或者我没有启用Double Buffering?
这是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Widget
{
public class Circle
{
public float X;
public float Y;
public float Radius;
public int Alpha;
public Circle(float X, float Y, float Radius, int Alpha)
{
this.X = X;
this.Y = Y;
this.Radius = Radius;
this.Alpha = Alpha;
}
}
public partial class Form1 : Form
{
public static readonly int ScreenX = Screen.PrimaryScreen.Bounds.Width;
public static readonly int ScreenY = Screen.PrimaryScreen.Bounds.Height;
public int WindowWidth = 500, WindowHeight = 500;
public Graphics G;
private Pen Pen;
private Timer timer = new Timer();
private List<Circle> Circles;
public Form1()
{
this.Text = "Widget - Sam Brandt";
this.Size = new Size(WindowWidth, WindowHeight);
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(ScreenX - WindowWidth - 100, 0);
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Icon = new Icon("C:\\Users\\Admin\\Desktop\\Code Repositories\\Visual Studios\\Widget\\Widget\\Properties\\WidgetIcon.ico");
Pen = new Pen(Color.Black, 1);
G = CreateGraphics();
//this.Paint += new PaintEventHandler(OnPaint);
ConstructMouse();
FormWithTimer();
DoubleBuffered = true;
Circles = new List<Circle>();
}
public void ConstructMouse()
{
this.MouseUp += new MouseEventHandler(OnMouseUp);
this.MouseMove += new MouseEventHandler(OnMouseMove);
this.MouseDown += new MouseEventHandler(OnMouseDown);
}
public void FormWithTimer()
{
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (10);
timer.Enabled = true;
timer.Start();
}
protected void OnMouseUp(object sender, MouseEventArgs e)
{
}
protected void OnMouseMove(object sender, MouseEventArgs e)
{
}
public void OnMouseDown(object sender, MouseEventArgs e)
{
Circles.Add(new Circle(e.Location.X, e.Location.Y, 0, 255));
}
/*public void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
e.Graphics.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius);
}
}*/
private void Tick()
{
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
C.Radius++;
C.Alpha -= 3;
if (C.Alpha == 0)
{
Circles.RemoveAt(i);
}
}
}
public void Render()
{
G.Clear(Color.White);
for (int i = 0; i < Circles.Count; i++)
{
Circle C = Circles[i];
G.DrawEllipse(new Pen(Color.FromArgb(C.Alpha, 0, 0, 0), 1), C.X - C.Radius, C.Y - C.Radius, 2 * C.Radius, 2 * C.Radius);
}
}
public void timer_Tick(object sender, EventArgs e)
{
Render();
Tick();
}
}
}
答案 0 :(得分:4)
简短回答 - 保持DoubleBuffered = true
并使用Paint
活动。
当我尝试将PaintEvent用于我的图形功能时,没有发生任何事情
当您进行一些修改并希望反映它们时,请使用Control.Invalidate方法,根据文档
使控件的整个表面无效并导致重绘控件。
在你的情况下,像这样
void timer_Tick(object sender, EventArgs e)
{
Tick();
Invalidate();
}
答案 1 :(得分:0)
此处有更多观察,但可能就是答案。
答案 2 :(得分:0)
我将所有绘图都绘制到一个单独的Graphics对象,然后只有在进行了更改时才将其复制到计时器tick事件的主Graphics对象上。您可能需要使用布尔成员跟踪它。这意味着您的背景图必须由其他一些事件触发。
如果您的图片实际上每10毫秒更换一次,我会稍微减慢计时器的速度并将其设置为50毫秒。
答案 3 :(得分:0)
试试这个(在VB中):
Dim aProp = GetType(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
aProp.SetValue(Me, True, Nothing)
双缓冲也有问题,而且通常设置属性DoubleBuffered为true不起作用。我在网上找到了这个解决方案