【问题标题】:Updating WPF control in "real time"“实时”更新 WPF 控件
【发布时间】:2011-03-24 20:58:12
【问题描述】:

我正在编写一个应用程序,它将显示相机看到的当前图像,它需要实时更新显示的图像,或者接近它。本质上,我有一台可以捕捉图像的相机,我需要每隔 1 秒捕捉一个图像并将该图像显示到屏幕上。目前,我的应用程序有一个 Image 控件,我正在从相机捕获 BitmapImage 并将其设置为 Image.Source。我的麻烦是让它不断更新。不幸的是,我没有处理这样的事情的经验,它必须永远更新自己(或者直到我正在编写的应用程序关闭),老实说,似乎很少甚至没有(我已经能够发掘)在web 关于在 WPF/C# 中做这样的事情。我怀疑我必须生成一个线程来执行图像捕获,但老实说,这是我的问题的一部分——我很少有使用线程的经验,而且对所有这些工作的原理有点困惑。非常感谢您提供的任何帮助。

【问题讨论】:

    标签: c# wpf multithreading real-time redraw


    【解决方案1】:

    要使数据绑定正确更新,您可以使用INotifyPropertyChanged。只需添加对 System.ComponentModel 的引用:

    using System.ComponentModel;
    

    然后继承接口:

    MyWindow : INotifyPropertyChanged
    

    然后添加以下代码:

    public event PropertyChangedEventHandler PropertyChanged;
    
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    

    最后,添加您要绑定的属性。

    private BitmapImage currentImage;
    public BitmapImage CurrentImage{get{return currentImage;} set{currentImage=value;NotifyPropertyChanged("CurrentImage");}}
    

    最后,在您的 xaml 中,将绑定更改为 {Binding CurrentImage},然后对于窗口,将数据上下文设置为相对源自身...这将是窗口的属性:

    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    

    这应该可以使绑定正常工作。在单独的线程上做事需要调度器

    【讨论】:

    • 将此答案与 dthorpe 的以下答案完美结合!非常感谢您使这个非常清晰和防伪;非常感谢。
    【解决方案2】:

    您应该阅读 WPF 中的数据绑定。 WPF 充满了观察者模式,一旦绑定的数据项发生更改,就会更新显示。您正在更改 Image.Source 而不是更改图像内容的事实可能是令人困惑的事情。您需要将 XAML 中的图像控件设置为数据绑定到位图对象(可能是表单的字段),然后根据需要更改或重新加载位图对象。数据绑定图像控件应在每次更改位图对象时自动重绘。

    由于您提到了后台线程,因此您需要注意仅在 UI 线程上修改 UI 元素(Image、Bitmap)的属性。如果您在后台线程中收到新图像并希望在 UI 中显示它,则需要将该更新同步到 UI 线程。见Dispatcher.Invoke()

    【讨论】:

    • 由于是WPF,使用Dispatcher是WPF与UI线程同步的方式。
    • 也许我没有正确理解这一点...... Image 控件没有 Content 属性,因此我将 Source 绑定到表单的属性。我试过: 但是,问题是当我稍后以编程方式设置 this.CurrentImage 时,它​​永远不会更新 Image 控件 - 我只是得到一个空白图片。我做错了什么吗?此外,为了每秒(或某个时间段)更新图像,您是否建议使用后台线程来更改表单 CurrentImage 属性或其他内容?再次感谢!
    • @JToland:如果您要绑定到您实现的属性,您还需要在包含该属性的类上实现 INotifyPropertyChanged,以便数据绑定机制可以发现该属性已更改并且作出相应的回应。在您的示例中,这将是表单类。查看 MSDN 上的示例实现:msdn.microsoft.com/en-us/library/ms229614.aspx
    • @JToland:如果获取或加载该位图的计算量很大或涉及阻塞操作(例如等待串行端口),那么这将是一个很好的理由将位图获取放入后台线程,因此它不会冻结您的 UI。否则,我会跳过线程的附加复杂性,只需在 UI 线程上的 1 秒计时器事件中加载您的位图。你可以用线程做很多事情,但你也可以在没有线程的情况下做很多同样的事情。 ;>
    • 我对此进行了跟进 - 我意识到它已经过时了,但不想重复一个问题。我有一个闪烁的问题。视频捕获线程生成位图,然后必须“冻结”它以将其传递给 WPF 窗口(否则我只会得到白色)。它使用 WPF 窗口的 Dispatcher 来调用调用。对于大多数帧绘制,我工作得很好,但偶尔它必须在屏幕刷新中间发生变化。有没有办法与屏幕刷新同步以避免闪烁?我宁愿一个框架被额外重绘而不是闪烁。
    【解决方案3】:

    我处于类似情况,只是图像是通过 WCF 传递给我的 WPF 客户端的。所以我设置了一个计时器并每隔1秒调用一次WCf服务。但是当我将 ImageSource 分配给 bitmapImage 时,图像会闪烁,就像我得到一个白屏一样,图像,白屏,图像 如何让它连续?

    【讨论】:

    • 您是否尝试过使用上述方法?我知道我的 CurrentImage 属性何时更改,并且当我使用上面讨论的通知器时,我的图像正在正确更改而没有任何闪烁。也许在实际设置“新”图像之前,您的“当前”图像正在从属性、内存或其他任何东西中清除?
    • 不,我还没有尝试过,因为我不完全了解要做什么。我是否要更改具有从 INotifyPropertyChanged 继承的 Image 元素的窗口?这样 MainWINdow : Window 更改为 MainWindow : INotifyPropertyChanged ??那么窗口中的其他元素呢?
    猜你喜欢
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2017-02-07
    相关资源
    最近更新 更多