使用TListView的VirtualTree技术来处理大量数据

2009年11月22日 | 标签: , , ,

自己重新构造头  
   
  你使用VirtualTree技术  
  如何用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中看到的数据就是排好序的数据了。   
————————————

重新构造头,不就什么都解决了吗  
  在ListView1Data灵活处理一下不就可以了吗  
   
          Item->Caption   =   plvData->Caption;    
        for(int   k=1;k<ListView1->ListView1->Columns;k++)  
          {  
            TListColumn   *t_Column=(TListColumn   *)ListView1->Column[k];  
            if(t_Colum->Caption==”")  
                Item->SubItems->Add(plvData->SubItems1);    
            ….  
   
          }  
引自http://topic.csdn.net/t/20030404/10/1617448.html

本文的评论功能被关闭了.