標籤:c# c#系統應用 圖片瀏覽 listview 基礎應用
最近有同學問我如何使用ListView載入圖片列表,前面在"C#系統應用"中TreeView+ListView+ContextMenuStrip控制項實現樹狀圖顯示磁碟目錄,並在ListView中顯示檔案的詳細資料.這裡準備簡單介紹下給同學講述的如何使用ListView+ImageList控制項實現簡單的圖片瀏覽器知識.
第一步 設計介面架構如所示,同時添加ImageList控制項(不可見)
注意:設定ListView控制項的Anchor屬性為Top,Bottom,Right;設定PictureBox的Anchor屬性為上下左右.
第二步 使用OpenFileDialog控制項開啟顯示圖片
//開啟圖片private void button1_Click(object sender, EventArgs e){ //設定開啟檔案控制項 OpenFileDialog openfile = new OpenFileDialog(); openfile.Filter = "JPG(*.JPG;*.JPEG);gif檔案(*.GIF);BMP檔案(*.BMP);PNG檔案(*.PNG)|*.jpg;*.jpeg;*.gif;*.bmp;*.png"; openfile.FilterIndex = 1; //當前選定索引 openfile.RestoreDirectory = true; openfile.FileName = ""; //對話方塊選擇確定按鈕 if (openfile.ShowDialog() == DialogResult.OK) { //FromFile從指定的檔案建立Image pictureBox1.Image = Image.FromFile(openfile.FileName); //圖片被展開或收縮適合pictureBox大小 pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; }}
圖片顯示效果如所示,需要注意的是在使用FromFile顯示圖片,可能圖片全螢幕顯示時會出現只出現部分圖片現象,我設定圖片為可展開或收縮StretchImage模式.
第三步 顯示圖片列表至ListView控制項中
主要通過控制項FolderBrowserDialog控制項開啟檔案夾,同時擷取檔案夾的路徑;在通過GetFiles("*.jpg")函數擷取jpg格式圖片,並擷取檔案夾中檔案增加至ImageList中,設定ListView的View屬性格式為LargeIcon大表徵圖格式顯示.
//添加命名空間using System.IO; //Directory目錄using System.Diagnostics; //Stopwatch顯示時間//定義變數private string folderDirPath; //圖片檔案夾地址private string picDirPath = null; //圖片路徑private List<string> imagePathList = new List<string>(); //擷取列表圖片路徑private int index; //擷取選中列表圖片序號//ListView和imageList顯示圖片列表private void button2_Click(object sender, EventArgs e){ try { //開啟選擇檔案夾對話方塊 FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); DialogResult result = folderBrowserDialog.ShowDialog(); if (result == DialogResult.OK) { //擷取使用者選擇的檔案夾路徑 this.folderDirPath = folderBrowserDialog.SelectedPath; //調用自訂函數顯示圖片列表至ListView控制項 ShowPicture(); } else if (result == DialogResult.Cancel) { MessageBox.Show("取消顯示圖片列表"); } } catch (Exception msg) { //報錯提示 未將對象引用設定到對象的執行個體 throw msg; } }//顯示圖片列表至ListView控制項private void ShowPicture(){ //提供一種方法測試回合時間 開始計算 //參考資料:http://www.cnblogs.com/newstart/archive/2012/09/21/2696884.html Stopwatch sw = new Stopwatch(); sw.Start(); //擷取目錄與子目錄 DirectoryInfo dir = new DirectoryInfo(folderDirPath); //擷取目前的目錄JPG檔案清單 GetFiles擷取指定目錄中檔案的名稱(包括其路徑) FileInfo[] fileInfo = dir.GetFiles("*.jpg"); //防止圖片失真 //參考資料:http://blog.csdn.net/cdefg198/article/details/7821891 (部落格中引用) this.imageList1.ColorDepth = ColorDepth.Depth32Bit; for (int i = 0; i < fileInfo.Length; i++) { //擷取檔案完整目錄 picDirPath = fileInfo[i].FullName; //記錄圖片源路徑 雙擊顯示圖片時使用 imagePathList.Add(picDirPath); //圖片載入到ImageList控制項和imageList圖片列表 this.imageList1.Images.Add(Image.FromFile(picDirPath)); } //顯示檔案清單 this.listView1.Items.Clear(); this.listView1.LargeImageList = this.imageList1; this.listView1.View = View.LargeIcon; //大表徵圖顯示 //imageList1.ImageSize = new Size(40, 40); //不能設定ImageList的映像大小 屬性處更改 //開始綁定 this.listView1.BeginUpdate(); //增加圖片至ListView控制項中 for (int i = 0; i < imageList1.Images.Count; i++) { ListViewItem lvi = new ListViewItem(); lvi.ImageIndex = i; lvi.Text = "pic" + i; this.listView1.Items.Add(lvi); } this.listView1.EndUpdate(); //顯示開啟圖片列表所需時間 sw.Stop(); long secords = sw.ElapsedMilliseconds; //毫秒單位 label1.Text += '\n' + (Convert.ToDouble(secords) / 1000).ToString(); //轉換為秒}
顯示結果如所示:
需要注意的是:
1.使用ListView載入資訊的幾個步驟:擷取檔案夾路徑 -> DirectoryInfo擷取目錄 -> GetFiles擷取檔案 -> Add圖片至ImageList -> Add圖片至ListView.
2.在設定ListView中圖片的大小時,使用imageList1.ImageSize = new Size(40, 40)賦值失敗,我是通過修改ImageList1的ImageSize屬性為(64,64)實現的.
3.顯示ListView中圖片,通常會出現失真的情況,主要原因參考部落格:ListView顯示圖片失真.
主要概括為ImageList裡面圖片顏色失真和圖片大小失真,其中圖片顏色失真原因是Design-Time在VS.NET中添加圖片時沒有使用使用者指定的ColorDepth(如Depth32Bit),而用了ImageList.ColorDepth的預設值(Depth8Bit).因此需要先設定圖片色彩深度,在再往ImageList中添加圖片,而圖片大小統一的都等於ImageList.ImageSize.
第四步 通過listView1_DoubleClick函數雙擊開啟圖片
在Form1.cs[設計]中ListView屬性頁面為其添加DoubleClick雙擊事件,並通過Image.FromFile顯示圖片.
//增加雙擊ListView事件 顯示圖片至PictureBoxprivate void listView1_DoubleClick(object sender, EventArgs e){ if (this.listView1.SelectedItems.Count == 0) return; //採用索引方式 imagePathList記錄圖片真實路徑 index = this.listView1.SelectedItems[0].Index; //顯示圖片 this.pictureBox1.Image = Image.FromFile(imagePathList[index]); //圖片被展開或收縮適合pictureBox大小 pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;}
雙擊列表中不同圖片的顯示效果如所示:
其中需要注意的是,我在列表中顯示圖片重新命名為"pic+數字",同時定義變數記錄檔案夾中圖片真實路徑與其一一對應.private List<string> imagePathList = new List<string>().這裡使用index顯示對應圖片即可,同樣顯示上一張\下一張相同.
第五步 顯示上一張\下一張
//顯示上一張圖片private void button3_Click(object sender, EventArgs e){ if (pictureBox1.Image != null) { if (index > 0) { index--; //顯示圖片 this.pictureBox1.Image = Image.FromFile(imagePathList[index]); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; } else if (index == 0) { index = imagePathList.Count; index--; //顯示圖片 this.pictureBox1.Image = Image.FromFile(imagePathList[index]); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; } }}//顯示下一張圖片private void button4_Click(object sender, EventArgs e){ if (pictureBox1.Image != null) { if (index == imagePathList.Count - 1) //最後一張圖片 { index = 0; //顯示圖片 this.pictureBox1.Image = Image.FromFile(imagePathList[index]); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; } else { index++; //顯示圖片 this.pictureBox1.Image = Image.FromFile(imagePathList[index]); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; } }}
文章寫到此處基本內容完成,內容比較簡單,但也構成了一個完整的圖片瀏覽器.同時很多時候我們需要上傳縮圖,可以調用下面函數(線上筆記):
//添加命名空間using System.Drawing.Drawing2D; //CompositingQuality.HighQualityusing System.Drawing.Imaging; //EncoderParameter/// <SUMMARY>/// 圖片無損縮放 自訂函數產生縮圖/// </SUMMARY>/// <PARAM name="sourceFile">圖片源路徑</PARAM>/// <PARAM name="destFile">縮放後圖片輸出路徑</PARAM>/// <PARAM name="destHeight">縮放後圖片高度</PARAM>/// <PARAM name="destWidth">縮放後圖片寬度</PARAM>/// <RETURNS></RETURNS>public static bool GetThumbnail(string sourceFile, string destFile, int destHeight, int destWidth){ System.Drawing.Image imgSource = System.Drawing.Image.FromFile(sourceFile); System.Drawing.Imaging.ImageFormat thisFormat = imgSource.RawFormat; int sW = 0, sH = 0; // 按比例縮放 int sWidth = imgSource.Width; int sHeight = imgSource.Height; if (sHeight > destHeight || sWidth > destWidth) { if ((sWidth * destHeight) > (sHeight * destWidth)) { sW = destWidth; sH = (destWidth * sHeight) / sWidth; } else { sH = destHeight; sW = (sWidth * destHeight) / sHeight; } } else { sW = sWidth; sH = sHeight; } //建立一個bmp圖片 Bitmap outBmp = new Bitmap(destWidth, destHeight); //建立一個畫板 Graphics g = Graphics.FromImage(outBmp); //清空畫布並以透明背景色填充 Color.Black黑色填充 g.Clear(System.Drawing.Color.Transparent); //設定畫布的描繪品質 g.CompositingQuality = CompositingQuality.HighQuality; //設定高品質,低速度呈現平滑程度 g.SmoothingMode = SmoothingMode.HighQuality; //設定高品質插值法 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //在指定位置並且按指定大小繪製原圖片的指定部分 g.DrawImage(imgSource, new Rectangle((destWidth - sW) / 2, (destHeight - sH) / 2, sW, sH), 0, 0, imgSource.Width, imgSource.Height, GraphicsUnit.Pixel); g.Dispose(); //以下代碼為儲存圖片時 設定壓縮品質 EncoderParameters encoderParams = new EncoderParameters(); long[] quality = new long[1]; quality[0] = 100; EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); encoderParams.Param[0] = encoderParam; try { //獲得包含有關內建映像編碼解碼器的資訊的ImageCodecInfo對象 ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICI = null; for (int x = 0; x < arrayICI.Length; x++) { if (arrayICI[x].FormatDescription.Equals("JPEG")) { jpegICI = arrayICI[x]; //設定JPEG編碼 break; } } //儲存為JPG格式圖片 if (jpegICI != null) { outBmp.Save(destFile, jpegICI, encoderParams); } else { outBmp.Save(destFile, thisFormat); } return true; } catch(Exception e) { throw e; } finally { imgSource.Dispose(); outBmp.Dispose(); }}
總結:本文主要是根據給同學講解ListView控制項顯示圖片寫的一篇文章,同時存在一個缺點圖片可能被扯拉變形,而且代碼中開啟ListView圖片時有個"開啟時間",主要是通過Stopwatch記錄批量開啟圖片所需時間,如果開啟大量圖片時我希望使用並行的方法實現,與其進行時間對比.同時如果對圖片處理感興趣的同學(C++通過Bitmap開啟變換)自己可以去研究.我希望的顯示效果想Google Picasa一樣快速批量顯示(研究ing).
:
最後希望文章對大家有所協助,如果有錯誤或不足之處,請海涵~
(By:Eastmount 2014-10-10 中午13點 原創CSDN http://blog.csdn.net/eastmount/)
C# 系統應用之ListView實現簡單圖片瀏覽器