【发布时间】:2020-07-02 17:07:19
【问题描述】:
所以我尝试用Winforms 制作一些动画,更具体地说,是从左到右的动画。但是,我遇到了多个问题。
首先,System.Windows.Forms.Timer 甚至像System.Threading.Timer 这样的其他 Timer 类对于我想要的动画来说还不够快。作为补偿,我可以增加添加到左右动画的像素数量。但是,这会导致动画不连贯,这不是我想要的。为了解决这个问题,我使用了自己的计时器(在另一个线程上),它更准确:
long frequency = Stopwatch.Frequency;
long prevTicks = 0;
while (true)
{
double interval = ((double)frequency) / Interval;
long ticks = Stopwatch.GetTimestamp();
if (ticks >= prevTicks + interval)
{
prevTicks = ticks;
Tick?.Invoke(this, EventArgs.Empty);
}
}
然而,这有其自身的缺点。首先,这会给 CPU 带来沉重的负担。其次,如果我想一次将左右动画增加 1 个像素以获得流畅的动画,我无法以足够快的速度重绘。解决这个问题的方法是直接在CreateGraphics提供的图形上绘制,效果还不错,除了我们去透明画笔的时候。然后,事情变慢了。
所有这一切的解决方案就是增加我在左右动画上一次绘制的像素数量,但这会导致动画缺乏平滑度。下面是一些测试代码:
private int index;
private Graphics g;
private Brush brush;
private void FastTimer_Tick(object sender, EventArgs e)
{
index++;
if (g == null)
{
g = CreateGraphics();
}
if (brush == null)
{
brush = new SolidBrush(Color.FromArgb(120, Color.Black));
}
g.FillRectangle(brush, index, 0, 1, Height);
}
我听说GDI 更快,因为它是硬件加速的,但我不知道如何使用它。
有人在坚持winforms 的同时有解决方案吗?谢谢。
编辑:这是一个示例视频: https://www.youtube.com/watch?v=gcOttFFCUz8&feature=youtu.be 当窗体最小化时,它非常平滑。但是,当表格最大化时,我必须补偿平滑度以提高速度。我想知道如何更快地重绘(可能使用 GDI),以便我仍然可以使用 +1px 动画,以获得流畅的体验。
【问题讨论】:
-
使用双缓冲控件作为 PictureBox 并在其 Paint 事件(或
OnPaint方法)中绘制您的形状。不要使用CreateGraphics()(另外,检查null是无关紧要的)。抗锯齿可以隐藏单步运动,但您应该使用浮点值来增加水平移位。看起来您想绘制一条移动线(如在声波计/分析仪中?)。然后,您可以使用 StopWatch 或 higher resolution timer 来生成这些值。您必须测试 UI 对此的反应。 -
感谢吉米的回复!我使用
CreateGraphics绘图,因为如果我不这样做,那么调用 Refresh 或 Invalidate 太慢了。另外,我正在尝试绘制一个与控件宽度和高度相同的移动矩形(大约是屏幕的大小)。 -
如果你在它的 Paint 事件中 Invalidate() 你的 Control ,那么只有当你的 Timer 说它是时间时才绘制。要比这更快地绘制,您需要另一个 Engine。 --
CreateGraphics()并没有更快:您实际上创建了两次该对象,因为它是在 Control 收到WM_PAINT消息时创建的。如果您尝试重用 store 对象,您将得到非常奇怪的结果(或完全错误,因为剪辑)或异常。 -- 这个:FillRectangle(brush, index, 0, 1, Height);没有画出你描述的内容。 -
除非你认为你可以让这条线坚持。你会失望的。
-
我已经尝试过您的解决方案,但是,它实际上并没有我在那里发布的代码那么快。此外,上面的代码确实产生了我想要的(只是不够快),因为在
CreateGraphics提供的对象上绘图不会使控件无效,所以那里的一切都保持原样。
标签: c# .net winforms animation gdi+