0

我正在尝试制作一组​​图片以设置为我的图像控件。有一个循环将遍历图片并显示一秒钟,直到它在随机图片上停止。

我的方法:我将图片路径存储在一个字符串中,然后将其放入一个数组中。在我的循环中,我创建了一个新的 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++;
        }

    }

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

提前谢谢。

4

2 回答 2

0

您的代码没有创建任何新线程。您的 UI 将冻结不是 WPF 的错。

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

此外,您在 WPF 中不需要任何这些。在 WPF 中,DataBinding如果您习惯了一些随机的恐龙无用框架(如 winforms),则无需在程序代码中操纵 UI 的所有这些可怕的黑客攻击。

这是执行您在 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 元素。
  • 我的示例从 Web 下载图像,因此如果您使用本地存储的图像,它应该会快得多。
  • 请注意 UI 是如何在任何时候都不会冻结的。仍然有一点延迟,因为实际的图像数据是从网络上下载的。该下载是在 UI 线程中执行的,因此您实际上可以改进我的示例以异步下载,但由于您使用的是本地存储的图像,所以没关系。
于 2013-06-21T15:42:45.737 回答
0

如果这是一个普通的 windows 窗体,你可以使用

this.Refresh() 

在 Sleep() 之前刷新屏幕(显示当前图像)。

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

无论如何,您必须将该逻辑放入 WPF 的新线程中。

于 2013-06-21T15:14:59.957 回答