2009/08/19

[轉載]加快你ADD Items的速度!virtual list、vector for TListview教學


寫這篇文章的人真的是佛心來的耶!超厲害的啦!希望我有一天也能夠寫出這樣的作品 ^___^

轉載自:300分求解决listview大量数据添加慢的方法

轉載內容

主  题:     讨论ListView里显示十万级以上记录时,象SQL   Server里的返回所有行的方式显示记录,怎么实现?

作  者:     cmsoft   (韦小宝是我的老乡)

等  级:

信   誉   值:     100

所属论坛:     C++   Builder   基础类

问题点数:     99

回复次数:     38

发表时间:     2002-12-31   9:57:02

回复人:   bigwhiteshark(大白鲨)   (   )

信誉:被封杀

哈哈正中本人下怀

如何用TListView来处理大量数据

采用常规方法处理ListView,在数据量大时无论是还是用了BeginUpdata和EndUpdata()

还是处理WM_EraseBkgnd信息都不会得到理想的效果,那答案是什么呢?嗯,

采用所谓Virtual ListView技术。说起来很神秘,其实点通了很简单。

通常ListView中的所有数据都是由ListView自己来管理的,它负责这些数据空间的分配和释放,

当你把ListView->OwnerData设为true时,ListView就把数据的管理权交给了你,而它只负责显示。

这时你需要自己来为数据分配和释放空间,至于你怎样来管理这些数据完全有你自己来定,

ListView完全不关心,当ListView需要显示某条数据时,它就调用OnData事件,

你只要在这个事件的处理函数里指定ListView即将显示的Item的内容就可以了。

这就是所谓的Virtual ListView技术。

由于ListView对数据管理的功能强大,随之而来的却是效率低下,

如果你采用更高效的数据管理方式就会极大的改变效率。

而且Virtual ListView只在数据需要显示时才调用OnData事件载入数据,所以速度很快。

下面的例子中,假设ListView中需要显示4列数据,所有的数据被保存在vector里。

/*Unit1.h*/
//---------------------------------------------------------------------------     
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------     
#include   <Classes.hpp>
#include   <Controls.hpp>
#include   <StdCtrls.hpp>
#include   <Forms.hpp>
#include   <ComCtrls.hpp>
#include   <vector.h>

using namespace std;
//---------------------------------------------------------------------------     

struct ListViewData //用於存儲一條資料的結構體     
{
  AnsiString Caption;
  AnsiString SubItems1;
  AnsiString SubItems2;
  AnsiString SubItems3;
};

class TForm1: public TForm
{
  __published: //   IDE-managed   Components     
    TListView * ListView1;
  void __fastcall ListView1Data(TObject * Sender, TListItem * Item);
  private: //   User   declarations     
    vector < ListViewData * > m_lvDataVector; //用於存儲所以資料的向量     
  public: //   User   declarations     
    __fastcall TForm1(TComponent * Owner);
  __fastcall~TForm1();
};

//---------------------------------------------------------------------------     

extern PACKAGE TForm1 * Form1;

//---------------------------------------------------------------------------     
#endif

/*unit1.cpp*/
//---------------------------------------------------------------------------     
#include   <vcl.h>
#pragma hdrstop#include   "Unit1.h"

//---------------------------------------------------------------------------     

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 * Form1;
//---------------------------------------------------------------------------     
__fastcall TForm1::TForm1(TComponent * Owner) : TForm(Owner)
{
  ListView1 -> OwnerData = true;
  const int iListViewCount = 5000;
  ListView1 -> Items -> Count = iListViewCount; //必須指定,以使ListView知道其虛擬資料量   

  //保存資料     
  for (int i = 0; i < iListViewCount; ++i) {
    ListViewData * plvData = new ListViewData;
    plvData -> Caption = "Caption" + AnsiString(i);
    plvData -> SubItems1 = "SubItems1" + AnsiString(i);
    plvData -> SubItems2 = "SubItems2" + AnsiString(i);
    plvData -> SubItems3 = "SubItems3" + AnsiString(i);
    m_lvDataVector.push_back(plvData); //向vector中添加一項     
  }
}

__fastcall TForm1::~TForm1()
{
  int iCount = ListView1 -> Items -> Count;
  for (int i = 0; i < iCount; ++i) {
    ListViewData * plvData = m_lvDataVector[i];
    delete plvData; //釋放資料佔用的資源     
  }
  m_lvDataVector.clear(); //清空vector中所有條目     
}
//---------------------------------------------------------------------------     

//ListView在要顯示某條資料時會調用這個函數   
void __fastcall TForm1::ListView1Data(TObject * Sender, TListItem * Item)
{
  if (Item -> Index > m_lvDataVector.size())
    return;

  ListViewData * plvData = m_lvDataVector[Item -> Index];

  //指定要顯示的條目的資料     
  Item -> Caption = plvData -> Caption;
  Item -> SubItems -> Add(plvData -> SubItems1);
  Item -> SubItems -> Add(plvData -> SubItems2);
  Item -> SubItems -> Add(plvData -> SubItems3);
}
//---------------------------------------------------------------------------

速度很快,5000条数据只要1秒左右. 在使用Virtual ListView方式时,如果要对数据排序,只需对你保存的内部数据(这里时vector对象)排序,然后ListView->Refresh()即可。

这时你在ListView中看到的数据就是排好序的数据了。

沒有留言:

張貼留言