WPF 加載和顯示 GIF 圖片的完整指南

WPF 加載和顯示 GIF 圖片的完整指南

在 WPF 中加載和顯示 GIF 圖片需要一些特殊處理,因為 WPF 的 Image 控件默認不支持動畫 GIF。

解決方案一:使用 WpfAnimatedGif 庫(推薦)

這是最簡單且功能最完整的方法。

實現步驟:

  1. 安裝 NuGet 包
    在 NuGet 包管理器中安裝 WpfAnimatedGif

    Install-Package WpfAnimatedGif
    
  2. XAML 實現

    <Window x:Class="GifDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:gif="http://wpfanimatedgif.codeplex.com"mc:Ignorable="d"Title="GIF 動畫演示" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 加載 GIF 圖片 --><Image x:Name="gifImage" gif:ImageBehavior.AnimatedSource="Assets/loading.gif"gif:ImageBehavior.RepeatBehavior="Forever"Stretch="Uniform"HorizontalAlignment="Center"VerticalAlignment="Center"/><!-- 控制面板 --><StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"><Button Content="開始" Click="PlayGif" Margin="5" Padding="10,5"/><Button Content="暫停" Click="PauseGif" Margin="5" Padding="10,5"/><Button Content="恢復" Click="ResumeGif" Margin="5" Padding="10,5"/><Button Content="停止" Click="StopGif" Margin="5" Padding="10,5"/><ComboBox x:Name="gifSelector" Margin="10,0" Width="150"SelectionChanged="GifSelectionChanged"><ComboBoxItem Content="加載動畫" Tag="Assets/loading.gif"/><ComboBoxItem Content="慶祝動畫" Tag="Assets/celebration.gif"/><ComboBoxItem Content="進度動畫" Tag="Assets/progress.gif"/></ComboBox></StackPanel></Grid>
    </Window>
    
  3. 代碼后臺

    using System.Windows;
    using WpfAnimatedGif;namespace GifDemo
    {public partial class MainWindow : Window{public MainWindow(){InitializeComponent();// 設置默認選擇gifSelector.SelectedIndex = 0;}// 播放 GIFprivate void PlayGif(object sender, RoutedEventArgs e){ImageBehavior.SetAnimatedSource(gifImage, new BitmapImage(new Uri("Assets/loading.gif", UriKind.Relative)));}// 暫停 GIFprivate void PauseGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Pause();}// 恢復播放private void ResumeGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Play();}// 停止 GIFprivate void StopGif(object sender, RoutedEventArgs e){ImageBehavior.GetAnimator(gifImage)?.Dispose();gifImage.Source = null;}// 切換 GIFprivate void GifSelectionChanged(object sender, RoutedEventArgs e){if (gifSelector.SelectedItem is ComboBoxItem item && item.Tag is string gifPath){var source = new BitmapImage(new Uri(gifPath, UriKind.Relative));ImageBehavior.SetAnimatedSource(gifImage, source);}}}
    }
    

解決方案二:使用自定義 GIF 解碼器

如果你不想使用第三方庫,可以使用自定義實現:

using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;namespace GifDemo
{public partial class MainWindow : Window{private Bitmap _gifBitmap;private BitmapSource[] _gifFrames;private int _currentFrame;private bool _isPlaying;private readonly DispatcherTimer _animationTimer = new DispatcherTimer();public MainWindow(){InitializeComponent();_animationTimer.Tick += NextFrame;}private void LoadGif(string path){// 清理現有資源StopGif();// 加載新 GIF_gifBitmap = new Bitmap(path);// 獲取幀數int frameCount = _gifBitmap.GetFrameCount(FrameDimension.Time);_gifFrames = new BitmapSource[frameCount];// 提取所有幀for (int i = 0; i < frameCount; i++){_gifBitmap.SelectActiveFrame(FrameDimension.Time, i);_gifFrames[i] = ToBitmapSource(_gifBitmap);}// 獲取幀延遲var frameDelay = GetFrameDelay(_gifBitmap);_animationTimer.Interval = TimeSpan.FromMilliseconds(frameDelay);// 顯示第一幀_currentFrame = 0;gifImage.Source = _gifFrames[0];// 開始播放PlayGif();}private int GetFrameDelay(Bitmap gif){const int PropertyTagFrameDelay = 0x5100;// 獲取幀延遲屬性var delayProperty = gif.GetPropertyItem(PropertyTagFrameDelay);// 默認延遲 (100ms)if (delayProperty == null) return 100;// 返回第一幀的延遲(以毫秒為單位)return BitConverter.ToInt32(delayProperty.Value, 0) * 10;}private BitmapSource ToBitmapSource(Bitmap bitmap){using (var memory = new MemoryStream()){bitmap.Save(memory, ImageFormat.Png);memory.Position = 0;var bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.StreamSource = memory;bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.EndInit();bitmapImage.Freeze();return bitmapImage;}}private void NextFrame(object sender, EventArgs e){if (!_isPlaying || _gifFrames == null) return;_currentFrame = (_currentFrame + 1) % _gifFrames.Length;gifImage.Source = _gifFrames[_currentFrame];}private void PlayGif(object sender = null, RoutedEventArgs e = null){_isPlaying = true;_animationTimer.Start();}private void PauseGif(object sender, RoutedEventArgs e){_isPlaying = false;_animationTimer.Stop();}private void StopGif(object sender = null, RoutedEventArgs e = null){_isPlaying = false;_animationTimer.Stop();_currentFrame = 0;gifImage.Source = _gifFrames?[0];}protected override void OnClosed(EventArgs e){base.OnClosed(e);_animationTimer.Stop();_gifBitmap?.Dispose();}}
}

解決方案三:使用 MediaElement(適用于簡單 GIF)

對于不需要透明背景的 GIF,可以使用 MediaElement:

<Window x:Class="GifDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="GIF 動畫演示" Height="450" Width="800"><Grid><!-- 使用 MediaElement 播放 GIF --><MediaElement x:Name="mediaElement" Source="Assets/loading.gif"LoadedBehavior="Play"UnloadedBehavior="Stop"Stretch="Uniform"HorizontalAlignment="Center"VerticalAlignment="Center"/><!-- 控制面板 --><StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="10"><Button Content="播放" Click="PlayGif" Margin="5" Padding="10,5"/><Button Content="暫停" Click="PauseGif" Margin="5" Padding="10,5"/><Button Content="停止" Click="StopGif" Margin="5" Padding="10,5"/></StackPanel></Grid>
</Window>
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private void PlayGif(object sender, RoutedEventArgs e){mediaElement.Play();}private void PauseGif(object sender, RoutedEventArgs e){mediaElement.Pause();}private void StopGif(object sender, RoutedEventArgs e){mediaElement.Stop();}
}

常見問題解決方案

1. GIF 不播放

  • 檢查文件路徑是否正確
  • 確保 GIF 文件已設置為 “Resource” 或 “Content” 生成操作
  • 驗證 GIF 文件是否損壞(用其他軟件打開測試)

2. 透明背景顯示為黑色

  • 使用支持透明背景的解決方案(如 WpfAnimatedGif)
  • 確保 GIF 本身支持透明
  • 在 Image 控件上設置 Background="Transparent"

3. 性能問題

  • 避免加載過多 GIF
  • 暫停不可見的 GIF
  • 降低 GIF 分辨率
  • 使用 BitmapCache 提高渲染性能:
    <Image.CacheMode><BitmapCache EnableClearType="True" RenderAtScale="1" />
    </Image.CacheMode>
    

4. 控制 GIF 播放次數

<Image gif:ImageBehavior.AnimatedSource="animation.gif"gif:ImageBehavior.RepeatBehavior="3x"/> <!-- 播放3次 -->

總結

在 WPF 中加載和顯示 GIF 圖片有以下幾種方法:

  1. 推薦方案:使用 WpfAnimatedGif NuGet 包

    • 優點:功能完整、支持透明背景、易于使用
    • 缺點:需要添加外部依賴
  2. 自定義解碼器

    • 優點:無外部依賴
    • 缺點:實現復雜、功能有限
  3. 使用 MediaElement

    • 優點:內置支持
    • 缺點:不支持透明背景、功能有限

對于大多數應用場景,推薦使用 WpfAnimatedGif 庫,它提供了最完整的 GIF 支持,包括:

  • 播放控制(播放、暫停、停止)
  • 速度調整
  • 播放次數控制
  • 透明背景支持
  • 事件通知(如幀改變、播放完成等)

通過本文提供的代碼示例,您可以輕松地在 WPF 應用中實現 GIF 加載和播放功能,并根據需要添加自定義控制功能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89655.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89655.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89655.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Node.js GET/POST請求詳解

Node.js GET/POST請求詳解 引言 Node.js作為一種基于Chrome V8引擎的JavaScript運行環境&#xff0c;以其高性能、非阻塞I/O模型和輕量級等特點&#xff0c;在服務器端開發中得到了廣泛應用。本文將詳細介紹Node.js中GET和POST請求的處理方法&#xff0c;幫助開發者更好地理解和…

C++string類(2)

3.string類對象的訪問及遍歷操作函數名稱功能說明operator[] &#xff08;重 點&#xff09;返回pos位置的字符&#xff0c;const string類對象調用beginendbegin獲取第一個字符的迭代器 end獲取最后一個字符下一個位置的迭代器rbeginrendrbegin獲取最后一個字符的迭代器 ren…

SQLShift:一款異構數據庫存儲過程遷移工具

SQLShift 是一款專注于解決企業級數據庫遷移難題的智能 SQL 方言轉換平臺&#xff0c;尤其擅長異構數據庫存儲過程的自動化遷移。 SQLShift 工具深度融合了 AI 與 SQL 語法專家模型&#xff0c;可以大幅提升遷移效率并降低人工適配風險。 功能特性 多源多目標&#xff1a;目前…

學習設計模式《十八》——備忘錄模式

一、基礎概念 備忘錄模式的本質是【保存和恢復內部狀態】。 備忘錄模式的思考序號備忘錄模式的思考說明1保存是手段&#xff0c;恢復才是目的標準的備忘錄模式保存數據的手段是通過內存緩存&#xff1b;廣義的備忘錄模式實現的時候&#xff0c;可以采用離線存儲的方式&#xff…

HOT100——排序篇Leetcode215. 數組中的第K個最大元素

文章目錄題目&#xff1a;Leetcode215. 數組中的第K個最大元素原題鏈接思路1代碼1思路2代碼2題目&#xff1a;Leetcode215. 數組中的第K個最大元素 原題鏈接 數組中的第K個最大元素 思路1 排序 排序后返回倒數第k個數 代碼1 思路2 使用priority_queue&#xff0c;大根堆&#x…

三維重建一: 相機幾何

參考這位大佬&#xff1a;https://zhuanlan.zhihu.com/p/458000359 一. 基本的投影模型 正如上面所說&#xff0c;相機是一個將三維物體投影為二維圖像的設備。 對于小孔相機&#xff0c;或者薄透鏡相機來說&#xff0c;基礎投影的數學模型可以表達為 我們把這個過程表達在笛…

mysql 字符集不一致導致索引失效問題

mysql 字符集不一致導致索引失效問題 問題&#xff1a; 兩張表&#xff0c;同一個字段&#xff0c;由于字符集不一致&#xff0c;導致雖然都有索引&#xff0c;在關聯查詢時&#xff0c;索引失效身份表 identity_info &#xff0c;查詢索引信息 show index from identity_info …

Linux內核設計與實現 - 第6章 內核數據結構

目錄1. 鏈表 (Linked Lists)2. 隊列 (Queues)3. 映射 (Maps)4. 二叉樹 (Binary Trees)5. 位圖 (Bitmaps)6. 其他數據結構性能考量1. 鏈表 (Linked Lists) 單向鏈表 vs 雙向鏈表 struct list_head 標準實現內核鏈表API&#xff1a;LIST_HEAD(), list_add(), list_del() 環形鏈表…

十五、K8s可觀測能力:日志收集

十五、K8s可觀測能力&#xff1a;日志收集 文章目錄十五、K8s可觀測能力&#xff1a;日志收集1、云原生日志框架-ECK介紹1.1 什么是ECK&#xff1f;1.2 ECK核心資源&#xff1a;1.3 生產級日志收集架構2、日志收集-ECK2.1 集群規劃2.2 ECK 安裝2.3 一鍵部署高可用 ES 集群2.4 一…

微服務變更?自動化測試利器Parasoft SOAtest修復快、準、穩!

微服務架構憑借靈活和可擴展的優勢越來越普及&#xff0c;但隨之而來的變更也成了開發團隊的“心頭大患”。服務之間依賴復雜&#xff0c;接口改來改去&#xff0c;不僅讓開發更費勁&#xff0c;還容易導致測試用例失效、測試效率下降&#xff0c;甚至埋下系統不穩的隱患。 自…

將Android Studio創建的一個apk工程放到Android15源碼中構建

背景描述&#xff1a;起初Android Studio創建的apk工程&#xff0c;為了方便系統版本發布和后期維護需要同時支持兩種構建方式&#xff1a;Android Studio Gradle構建 IDE界面環境&#xff0c;對習慣java環境變成的友好、UI設計方便看效果Android15系統構建時自動構建 So…

yolo8目標檢測+訓練(識別和平精英人物)

?步驟一&#xff1a;安裝 PyTorch&#xff08;M1 專用&#xff09;# 推薦使用官方 MPS 后端&#xff08;Apple Metal 加速&#xff09; pip install torch torchvision torchaudio確認是否使用了 Apple MPS&#xff1a;import torch print(torch.backends.mps.is_available()…

【ArcGISPro】修改conda虛擬安裝包路徑

問題在ArcGISPro中經常使用克隆&#xff0c;導致C盤默認虛擬安裝包內存越來越大&#xff0c;導致電腦很卡解決方案打開ArcGISPro所在conda文件夾D:\Program Files\ArcGIS\Pro\bin\Python\Scripts打開命令行工具&#xff08;如 CMD 或終端&#xff09;。輸入以下命令&#xff0c…

三格電子—西門子PLC串口轉網口模塊

一、功能概述本文檔是西門子PLC串口轉以太網系列產品&#xff0c;包含SG-S7-200-ETH、S7-200-ETH(2P)&#xff0c;SG-S7-300-ETH&#xff0c;SG-S7-300-ETH(2P)共四個產品。使用框圖如下圖所示意。1.1 產品功能本系列產品用來給西門子S7-200/300 PLC串口擴展出網口來&#xff0…

Python—requests模塊

Python requests 模塊代碼演示 requests 是 Python 中一個簡單易用的 HTTP 庫&#xff0c;用于發送各種 HTTP 請求。下面是一些常見的使用示例&#xff1a; 1. 基本 GET 請求 import requests# 發送 GET 請求 response requests.get(https://api.github.com)# 檢查請求是否成功…

華為倉頡編程語言語法簡介與示例

華為倉頡編程語言語法簡介與示例 倉頡編程語言是華為自主研發的新一代通用編程語言&#xff0c;由南京大學馮新宇教授團隊主導設計&#xff0c;于 2024 年華為開發者大會&#xff08;HDC&#xff09;正式發布&#xff0c;并在 2025 年 7 月推出首個長期支持版本&#xff08;LTS…

觸發器的創建

- 建立product表&#xff0c;操作方式operate表要求1.定義觸發器實現在產品表(product)中每多一個產品,就在操作表(operate)中記錄操作方式和時間以及編號記錄。注&#xff1a;操作說明&#xff1a;標記執行delete 、insert、update2.定義觸發器實現在產品表(product)中每更新一…

論文略讀: RASA: RANK-SHARING LOW-RANK ADAPTATION

ICLR 2025盡管 LoRA 有諸多優勢&#xff0c;但近期研究表明&#xff0c;它在大規模訓練數據集和復雜任務&#xff08;如數學推理和代碼生成&#xff09;中&#xff0c;仍然落后于全參數微調&#xff08;FFT&#xff09;一個合理的解釋是&#xff1a;低秩約束限制了 LoRA 的表達…

VSCode - VSCode 查找中文字符

VSCode 查找中文字符 1、查找中文字符使用快捷鍵 Ctrl F 打開查找框點擊正則表達式按鈕 .*在搜索框中輸入 [\u4e00-\u9fa5]&#xff0c;這個范圍涵蓋了基本的中文字符2、查找中文字符串使用快捷鍵 Ctrl F 打開查找框點擊正則表達式按鈕 .*在搜索框中輸入 [\u4e00-\u9fa5]&a…

SQL基礎操作指南:增刪改查入門

前言 在日常數據庫操作中&#xff0c;掌握增刪查改是每個開發者必備的技能。下面我將通過實例解析SQL的核心操作要點&#xff0c;幫你避開常見陷阱。一、新增數據&#xff08;INSERT&#xff09; 單行插入&#xff1a;明確指定字段和值 INSERT INTO 表名(字段1, 字段2) VALUES …