【问题标题】:how to load thumbnails in listview as needed?如何根据需要在列表视图中加载缩略图?
【发布时间】:2014-10-23 20:37:49
【问题描述】:

所以我希望能够根据图像文件路径列表填充 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) 如何检测列表视图中的滚动事件?

【问题讨论】:

  • 在 Google 上搜索如何将缩略图或图像添加到 ListViewItem 这里是以前的SO 在此期间发布stackoverflow.com/questions/17151776/…
  • 我的问题是不知道如何添加缩略图。它按原样工作。当我添加太多缩略图时会出现问题。
  • 如何调试代码也许还有其他你不知道的事情发生..也许你需要在将项目添加到 ListView.Items @987654324 后释放这一行中的项目@ 但我敢打赌,一旦你通过代码,你可能会发现一些东西
  • 我确实调试了代码......它卡在这一行“this.imageList1.Images.Add(Image.FromFile(file));”如果我添加到许多缩略图。如果我将列表减少到 100 则一切正常。问题是它的内存不足。这就是为什么我尽量不把它们都画出来。
  • this.ListView.View = View.LargeIcon;您是否认为图像的大小也可能导致问题..您是否考虑过重新调整 ImageSize 的大小...??

标签: c# winforms listview imagelist


【解决方案1】:

这是相当棘手的。

你有两个问题:

  • 您需要知道需要显示哪些图片
  • 您需要确保不会耗尽内存或 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;;然后将调用DrawItem 事件,在设置e.DrawDefault = true; 之后,实际绘图将由系统完成。

但该事件会不断告诉您哪些项目是可见的。

现在您可以确保将相应的位图加载到您的 ImageList 中,或者再次处理那些遥远的位图。到目前为止,我只实现了按需加载..

更新:像 Plutonix 一样,我已经运行了一些测试,并且可以加载 3000 张图像,每张 128x128 像素,完全没有任何问题。我按需加载它们,看起来 ImageList 处理得很好:无需处理图像,GDI 资源对于我的最新程序保持在低水平(

imageList1.Images.Clear();

..然后记忆又回到了起点。显示工作正常,列表的重新加载开始时没有故障。事实上,我不再使用 visibleItems 列表。我将其保留在答案中,因为这是了解这些项目的可行方法,但 atm 我认为不需要它..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多