启动画面上的淡入淡出效果

4

我正在尝试在WPF应用程序的启动画面上制作淡入效果。 图像对象的不透明度最初为0。这段代码将修改不透明度从0(最小)到1(最大),但是img_waves.Opacity这行代码就是不起作用。图像的不透明度仍然是0。

private void Splash_ContentRendered(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(3000);
        for (double x = 0; x<=1; x+=0.01d)
        { 
            System.Threading.Thread.Sleep(15);
            //MessageBox.Show(x.ToString());
            img_waves.Opacity = x;
        }
        this.Close();
    }

但是,如果我激活了这行代码 ´MessageBox.Show(x.ToString());´,就像您在这张图片中看到的那样:Code is working 代码可以工作,但我必须不停地点击消息框。我的问题是:为什么?为什么没有 MessageBox.Show 就不能工作呢?

只是一个猜测,尝试在每次迭代中刷新组件? - Max
2个回答

3

因为你正在阻塞GUI线程,导致它无法重新绘制表单。当你添加消息框时,消息队列被激活,从而允许绘图。

处理这个问题的最简单方法是这样的:

private async void Splash_ContentRendered(object sender, EventArgs e)
{
    await Task.Delay(3000);

    for (double x = 0; x<=1; x+=0.01d)
    { 
        await Task.Delay(15);

        img_waves.Opacity = x;
    }

    this.Close();
}

请注意,这意味着在动画期间仍然可以与表单进行交互。这对于启动屏幕不应该是问题,但在“真实”表单中可能会引起麻烦。仍然要确保在动画期间无法关闭表单 - 这可能会导致异常 :)
此外,还有其他方法可以强制消息队列被处理,但通常不建议使用。
所有这些都说了,你正在使用WPF - 为什么要像这样手动执行动画?你不能将其作为WPF中的动画效果处理吗?在MSDN上有一个示例。

谢谢您的回复,Luaan。我猜 Task.Delay 是 .NET 4.5 中的。我正在使用 .NET 3.5。但是,现在我已经明白了我的问题所在。谢谢! - Kennedy Souza
如果你被困在.NET 3.5上,那就有点棘手了。我建议使用WPF本地解决方案——使用动画效果。 - Luaan
谢谢!现在我正在寻找如何做到这一点! :) 这是我的第一个C#应用程序。 - Kennedy Souza

1

虽然我同意@Luaan的解释,他提供了一个替代方案,使用StoryboardDoubleAnimationOpacity属性上进行循环

private void Splash_ContentRendered(object sender, EventArgs e)
{
    var sb = new Storyboard();
    var da = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(1.5)));
    da.BeginTime = TimeSpan.FromSeconds(3);
    Storyboard.SetTargetProperty(da, new PropertyPath("Opacity"));
    Storyboard.SetTarget(da, img_waves);
    sb.Children.Add(da);
    sb.Completed += (s1, e1) => this.Close();
    sb.Begin();
}

我用一种在巴西被称为“gambiarra”的方法解决了我的问题。我为.net 3.5自己制作了“task.delay”,但是你的代码更好!哈哈哈 - Kennedy Souza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接