最近刚接触WPF, 一边学着一边用着,知识点还没有系统化的进行学习整理.
现在手上有一些美术做好的图片,需要连起来观看形成动画的效果,由于需求比较急,一时半会也静不下心来看WPF关于动画的知识.
潜意识里一个Image控件,循环设定Source属性,一看效果总是显示集合的最后一项.难道是循环速度太快?基于此思路下折腾了好久也无结果。开始不得不借着可以找到的资源进行尝试。试想我们一张张的图片进行播放形成的动画,是不是类似帧的这种概念.顺这个便找到了CompositionTarget.Rendering事件创建基于帧的动画.
第一种尝试:
namespace ImgAniDemo { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { ObservableCollection<BitmapImage> bmList; public MainWindow() { InitializeComponent(); InitList(); CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); } public void InitList() { bmList = new ObservableCollection<BitmapImage>(); for (int i = 1; i < 4; i++) { BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg")); bmList.Add(bmImg); } } void CompositionTarget_Rendering(object sender, EventArgs e) { for (int i = 0; i < bmList.Count; i++) { this.imgViewer.Source = bmList[i]; this.imgViewer.Width = this.imgViewer.Source.Width; this.imgViewer.Height = this.imgViewer.Source.Height; } } } }
运行程序ImgAniDemo.exe结果还是只显示了最后一幅图片.
回头认真思考一下,可以做一个这样的猜测,WPF是不是做了优化,如果循环去设置Image的Source属性,用户看到的效果只会是最后一张图片呢?
Render是什么意思?不错,Rendering事件被处理的时候,我们是用了一个循环,按着上面的猜测,只会显示最后一张图片便在情理之中了.
聪明的你一定是想到了方法,我们在Rendering事件的时候不去循环了,只指定某一个图片给Source属性不就ok了吗?
修改后的代码:
namespace ImgAniDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<BitmapImage> bmList;
int index = 0; //记录索引
public MainWindow()
{
InitializeComponent();
InitList();
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
public void InitList()
{
bmList = new ObservableCollection<BitmapImage>();
for (int i = 1; i < 4; i++)
{
BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg"));
bmList.Add(bmImg);
}
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (index < bmList.Count)
{
this.imgViewer.Source = bmList[index];
this.imgViewer.Width = this.imgViewer.Source.Width;
this.imgViewer.Height = this.imgViewer.Source.Height;
index++;
}
else
{
index = 0;
}
}
}
}
这时候我们已经可以看到图片在自动切换了.会不会感觉速度太快了,我想按着一定的速度来控件切换怎么办?
直接上代码了
namespace ImgAniDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<BitmapImage> bmList;
int index = 0; //记录索引
bool isRendering = false;
public MainWindow()
{
InitializeComponent();
InitList();
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
isRendering = true;
System.Threading.Thread.Sleep(1000); //停1秒
}
}
public void InitList()
{
bmList = new ObservableCollection<BitmapImage>();
for (int i = 1; i < 4; i++)
{
BitmapImage bmImg = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\" + i.ToString() + ".jpg"));
bmList.Add(bmImg);
}
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (isRendering)
{
if (index < bmList.Count)
{
this.imgViewer.Source = bmList[index];
this.imgViewer.Width = this.imgViewer.Source.Width;
this.imgViewer.Height = this.imgViewer.Source.Height;
index++;
}
else
{
index = 0;
}
isRendering = false;
}
}
}
}
在运行看下效果呢?
呵呵,图片是不是在自动播放呢?
注:以上代码中用到的图片名称分别为1.jpg,2.jpg,3.jpg,且图片放在exe程序一起即可
以上仅是个人想到的一种方法,若有不正确的地方,还请多多指点...