如何根据需要在列表视图中加载缩略图
本文关键字:视图 加载 略图 列表 何根 | 更新日期: 2023-09-27 18:27:34
所以我希望能够基于图像文件路径列表填充1000个缩略图。我尝试使用以下代码,但我意识到在200多个图像之后,我的程序会向我抛出"System.Drawing.dll中发生了类型为"System.OutOfMemoryException"的第一次机会异常"。
private void PopulateThumbnails(List<string> queryResults)
{
this.playerListView.Items.Clear();
this.imageList1.Images.Clear();
ImageViewer imageViewer = new ImageViewer();
foreach (string file in queryResults)
{
try
this.imageList1.Images.Add(Image.FromFile(file));
catch
Console.WriteLine("This is not an image file");
}
this.ListView.View = View.LargeIcon;
this.imageList1.ImageSize = new Size(256, 144);
this.ListView.LargeImageList = this.imageList1;
for (int j = 0; j < this.imageList1.Images.Count; j++)
{
ListViewItem item = new ListViewItem();
item.ImageIndex = j;
this.ListView.Items.Add(item);
}
}
我意识到我可能只应该根据需要填充缩略图,但是。。。a) 我如何知道列表视图中加载了多少项?b) 如何在列表视图中检测滚动事件?
这相当棘手。
你有两个问题:
- 您需要知道需要显示哪些图像
- 您需要确保不会耗尽内存或GDI资源
不幸的是,ListView
对通知您滚动或告诉您哪些项目可见的事件或属性没有帮助。
这里有一小段代码,至少可以完成后者;它将几千个文件名加载到列表图像中,并保持100个项目的列表,最后可见:
List<string> images = new List<string>();
List<int> visibleItems = new List<int>();
void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
// this loads the images on demand:
if (!imageList1.Images.ContainsKey(images[e.ItemIndex]) )
{ loadImage(e.ItemIndex); e.Item.ImageIndex = imageList1.Images.Count - 1; }
// this makes sure the listView is drawn by the system
e.DrawDefault = true;
// these lines would maintain a list of items that are or were recently visible
if (!visibleItems.Contains(e.ItemIndex)) visibleItems.Add(e.ItemIndex);
if (visibleItems.Count > 1000)
{
visibleItems.Clear();
imageList1.Images.Clear();
listView1.Invalidate();
}
}
void loadImage(int index)
{
imageList1.Images.Add(images[index], new Bitmap(images[index]) );
}
您需要设置ListView.OwnerDraw = true;
;则将调用CCD_ 3事件,并且在设置CCD_。
但该事件将不断告诉您哪些项目是可见的。
现在,您可以确保在ImageList中加载相应的位图,或者再次处理远处的位图。。到目前为止,我只实现了按需加载。。
更新:像Plutonix一样,我已经运行了一些测试,可以加载3000个128x128像素的图像,而没有任何问题。我按需加载它们,看起来ImageList处理得很好:不需要处理图像,GDI资源对我的thest程序来说保持在较低水平(<100)。当我滚动时,内存foorprint一直在上升,但看起来不会有问题。它是我可以简单地做一个
imageList1.Images.Clear();
并且记忆下降回到起点。显示工作正常,重新加载列表开始时没有出现故障。。事实上,我不再使用visibleItems列表了。我把它保留在答案中,因为这是了解这些项目的可行方法,但我认为没有必要。