2013-06-21 27 views
0

我想制作一组图片来设置我的图片控件。有一个循环会遍历图片并每秒显示一次,直到它停在随机图片上。如何创建一个ImageSource类型的数组?

我的方法:我将图片路径存储在一个字符串中,然后放入数组中。在我的循环内部,我创建了一个新的ImageSource,并通过将它显示出来的数组项来定义它。我相信我的程序无法工作的原因是ImageSource无法从文件中拉出图像,并在睡眠线程让图片显示一秒钟之前将其设置为图像控制器足够快。

这里是我的代码(假设字符串是正确的路径,我试过无数的Thread.Sleep()变量)

此代码运行,但它只是显示,而不是通过所有的人都迅速翻转,然后停在最后一张照片最后一张照片。

将使类型ImageSource的数组保持图片“手上”显示更快? WPF可以支持获取和设置图像到图像控制器所需的速度吗? 在设置和显示图像之前,我的睡眠线程是否会执行得太快?

private void ButtonClick(object sender, RoutedEventArgs e) 
{ 
    String[] picArray = new String[] { kristen, justin, brandon, sarah, miles, nina };  
    int i = 0;  
    x = rnd.Next(0,5); 

     while (i < rnd.Next(10,50)) 
     { 
      ImageSource _currentPic = new BitmapImage(new Uri(picArray[x]));        
      cImage.Source = _currentPic; 
      if (x == 5) 
       x = 0; 
      else 
       x++; 

      Thread.Sleep(100); 
      i++; 
     } 

    } 

循环停止在数组中的“随机”点上,以随机化其方法结束的图片。

提前致谢。

+0

'ImageSource []',它肯定会更快地依赖于你如何存储它们,如果你只是保持它们在本地方法,那么这将需要更长的时间 – Sayse

+0

不涉及你的问题,但看起来你在UI线程上执行一些长操作,特别是在那里使用'Thread.Sleep()'调用。你可能想考虑改变它。 – Steve

+0

我试图使用ImageSource [],但它不会让我创建和该类型的数组。关于thread.sleep(),我没有太多考虑。会使用计时器更有效吗? – meisenman

回答

0

如果这是一个正常的Windows窗体,你也可以使用

this.Refresh() 

之前的睡眠()刷新屏幕(显示当前图像)。

但是,由于它是WPF,因此必须将该循环生成为单独的线程(例如BackgroundWorker)。另一种选择是设置Timer,每次定时器执行时只调用循环的内容。

无论如何,您必须将该逻辑关闭到WPF的新线程中。

+0

在WPF Window类中没有这样的方法。我想在WinForms中提到'Control.Refresh'。 – Clemens

+0

我喜欢刷新的想法,以确保它是当前正在显示的图片。当我的程序具有我可以在图片循环运行时使用的功能时,我最终添加了一个新线程。 – meisenman

+0

Bah!是的,这是旧的Windows窗体,而不是WPF。进入WPF,问题变得更加复杂。 (修订版) – Richard

0

您的代码不会创建任何新线程。你的用户界面不会冻结,这不是WPF的错。

在UI中执行Thread.Sleep()线程只会让您的应用程序冻结,无论WPF与否。

此外,你不需要在WPF中的任何。在WPF中,有DataBinding,这就消除了在程序代码中操纵用户界面的所有可怕黑客的需求,如果您习惯了一些随机的恐龙无用框架(如winforms),那么您可能会习惯这样做。

这里做你在WPF描述什么是正确的方法:

<Window x:Class="MiscSamples.SlideShowSample" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="SlideShowSample" Height="300" Width="300"> 
    <Image Source="{Binding ImageSource}"/> 
</Window> 

代码背后:

public partial class SlideShowSample : Window 
{ 
    public SlideShowSample() 
    { 
     InitializeComponent(); 
     DataContext = new SlideShowViewModel(); 
    } 
} 

视图模型:

public class SlideShowViewModel:PropertyChangedBase 
{ 
    public const string SourceURL = "http://lorempixel.com/400/200/sports/"; 

    private string _imageSource; 
    public string ImageSource 
    { 
     get { return _imageSource; } 
     set 
     { 
      _imageSource = value; 
      OnPropertyChanged("ImageSource"); 
     } 
    } 

    private System.Threading.Timer _slideShowTimer; 
    private System.Random _random = new Random(); 

    public SlideShowViewModel() 
    { 
     _slideShowTimer = new Timer(x => OnTimerTick(), null, 1000, 3000); 
    } 

    private void OnTimerTick() 
    { 
     ImageSource = SourceURL + _random.Next(1, 10).ToString(); 
    } 
} 

PropertyChangedBase(MVVM助手类) :

public class PropertyChangedBase:INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      Application.Current.Dispatcher.BeginInvoke((Action) (() => 
                    { 
                     PropertyChangedEventHandler handler = PropertyChanged; 
                     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
                    })); 
     } 
    } 
  • 了解我的代码如何不操纵任何UI元素。
  • 我的示例从网上下载图像,因此如果您使用本地存储的图像,它应该快得多。
  • 请注意UI在任何时候都不会冻结。还有一点延迟,因为实际的图像数据正在从网上下载。该下载是在UI线程中执行的,所以你可以改进我的示例以下载异步,但由于您使用的是本地存储的映像,因此无关紧要。
+0

谢谢你给我展示了这样一个精心制作的样本,并清除了我的恐龙方法引发的很多问题。我只是在工作中得到一份任务,所以我会尽快测试代码。我真的没有真正进入官方视图模型,并可能需要帮助简单地说明哪些类属于哪个类,或者如何修改它以满足我的确切需求。再次感谢 – meisenman

+0

我刚测试过这段代码。我与公共SlideShowViewModel()有问题。更具体地说它表示定时器不会占用4个参数。 – meisenman

+1

@muffinMan'计时器'是一个'System.Threading.Timer',检查你的使用情况。 –

相关问题