Chinaunix首页 | 论坛 | 博客
  • 博客访问: 544686
  • 博文数量: 252
  • 博客积分: 6057
  • 博客等级: 准将
  • 技术积分: 1635
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-21 10:17
文章分类

全部博文(252)

文章存档

2013年(1)

2012年(1)

2011年(32)

2010年(212)

2009年(6)

分类: C/C++

2010-07-02 13:30:12

一、

ListView在操作大量数据时慢的问题! (CSDN-CSDN社区-C++ Builder-基础类) :

--> 26楼   max_wzg (暴走-银狼) :

采用常规方法处理ListView,在数据量大时无论是还是用了BeginUpdata和EndUpdata()还是处理 WM_EraseBkgnd信息都不会得到理想的效果,那答案是什么呢?
嗯,采用所谓Virtual   ListView。
说起来 很神秘,其实点通了很简单。
在于把ListView-> OwnerData设为true,然后直接设置
ListView-> Items-> Count为数据总数,实际的数据可以保在任意其它速度较快且可直接索引的容器里(如STL中的vector),然后关键是在OnData事件中写入代码 通过Item-> Index从容器中(如vector)取出数据,然后用
Item-> Caption   =   ???;
Item-> SubItems-> Add(???);
Item-> SubItems-> Add(???);
来动态的写 入数据到ListView用于UI显示,如此Virtual   ListView即完成.

一个完整的简单例子如下:

  1. /*Unit1.h*/   
  2. //---------------------------------------------------------------------------   
  3.   
  4. #ifndef   Unit1H   
  5. #define   Unit1H   
  6. //---------------------------------------------------------------------------   
  7. #include      
  8. #include      
  9. #include      
  10. #include      
  11. #include      
  12. #include      
  13. using   namespace   std;   
  14. //---------------------------------------------------------------------------   
  15. struct   ListViewData   
  16. {   
  17.         AnsiString   Caption;   
  18.         AnsiString   SubItems1;   
  19.         AnsiString   SubItems2;   
  20.         AnsiString   SubItems3;   
  21. };   
  22. class   TForm1   :   public   TForm   
  23. {   
  24. __published: //   IDE-managed   Components   
  25.         TListView   *ListView1;   
  26.         void   __fastcall   ListView1Data(TObject   *Sender,   TListItem   *Item);   
  27. private//   User   declarations   
  28.         vector    m_lvDataVector;   
  29. public//   User   declarations   
  30.         __fastcall   TForm1(TComponent*   Owner);   
  31.         __fastcall   ~TForm1();           
  32. };   
  33. //---------------------------------------------------------------------------   
  34. extern   PACKAGE   TForm1   *Form1;   
  35. //---------------------------------------------------------------------------   
  36. #endif   
  37.   
  38. /*unit1.cpp*/   
  39. //---------------------------------------------------------------------------   
  40.   
  41. #include      
  42. #pragma   hdrstop   
  43.   
  44. #include   "Unit1.h "   
  45. //---------------------------------------------------------------------------   
  46. #pragma   package(smart_init)   
  47. #pragma   resource   "*.dfm "   
  48. TForm1   *Form1;   
  49. //---------------------------------------------------------------------------   
  50. __fastcall   TForm1::TForm1(TComponent*   Owner)   
  51.         :   TForm(Owner)   
  52. {   
  53.         ListView1-> OwnerData   =   true;   
  54.         const   int   iListViewCount   =   5000;   
  55.         ListView1-> Items-> Count   =   iListViewCount;   
  56.         for(int   i   =   0;   i   <   iListViewCount;   ++i)   {   
  57.                 ListViewData   *plvData   =   new   ListViewData;   
  58.                 plvData-> Caption   =   "Caption "   +   AnsiString(i);   
  59.                 plvData-> SubItems1   =   "SubItems1 "   +   AnsiString(i);   
  60.                 plvData-> SubItems2   =   "SubItems2 "   +   AnsiString(i);   
  61.                 plvData-> SubItems3   =   "SubItems3 "   +   AnsiString(i);   
  62.                 m_lvDataVector.push_back(plvData);   
  63.         }   
  64. }   
  65.   
  66. __fastcall   TForm1::~TForm1()   
  67. {   
  68.         int   iCount   =   ListView1-> Items-> Count;   
  69.         for(int   i   =   0;   i   <   iCount;   ++i)   {   
  70.                 ListViewData   *plvData   =   m_lvDataVector[i];   
  71.                 delete   plvData;   
  72.         }   
  73. }   
  74. //---------------------------------------------------------------------------   
  75.   
  76. void   __fastcall   TForm1::ListView1Data(TObject   *Sender,   TListItem   *Item)   
  77. {   
  78.         ListViewData   *plvData   =   m_lvDataVector[Item-> Index];   
  79.         Item-> Caption   =   plvData-> Caption;   
  80.         Item-> SubItems-> Add(plvData-> SubItems1);   
  81.         Item-> SubItems-> Add(plvData-> SubItems2);   
  82.         Item-> SubItems-> Add(plvData-> SubItems3);   
  83. }   
  84. //---------------------------------------------------------------------------   

--> 28楼  cdws222  (二当家) :
不过如果你看到这个回复候能不能解释一下
vector   m_lvDataVector;是什么意思
我是个菜鸟,还不会这个

--> 29楼  max_wzg (暴走-银狼) :

vector是标准C++库的一部分,STL中的容器类之一,
你可以简单地把它理解为C++内置数组的增强版,详细的你可以 看看有关标准C++的书或文章,可以把这当成开始学习泛形编程的一个好的开端,推荐《C++Primer》。
学好标准C++库非常重要,既然用 BCB,就要充分发挥C++的强大功能,不然真的还不如去用Delphi.

二、

讨论ListView里显示十万级以上记录时,象 SQL Server里的返回所有行的方式显示记录,怎么实现?  (CSDN-CSDN社区-C++ Builder-基础类) :

--> 25楼  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里。

  1. /*Unit1.h*/     
  2.   
  3. //---------------------------------------------------------------------------     
  4.   
  5. #ifndef   Unit1H     
  6. #define   Unit1H     
  7. //---------------------------------------------------------------------------     
  8.   
  9. #include        
  10. #include        
  11. #include        
  12. #include        
  13. #include        
  14. #include        
  15.   
  16. using   namespace   std;     
  17.   
  18. //---------------------------------------------------------------------------     
  19.   
  20. struct   ListViewData         //用于存储一条数据的结构体     
  21. {     
  22.         AnsiString   Caption;     
  23.         AnsiString   SubItems1;     
  24.         AnsiString   SubItems2;     
  25.         AnsiString   SubItems3;     
  26. };     
  27.   
  28. class   TForm1   :   public   TForm     
  29. {     
  30. __published:         //   IDE-managed   Components     
  31.         TListView   *ListView1;     
  32.         void   __fastcall   ListView1Data(TObject   *Sender,   TListItem   *Item);     
  33. private:         //   User   declarations     
  34.         vector    m_lvDataVector;         //用于存储所以数据的向量     
  35. public:                         //   User   declarations     
  36.         __fastcall   TForm1(TComponent*   Owner);     
  37.         __fastcall   ~TForm1();           
  38. };     
  39.   
  40. //---------------------------------------------------------------------------     
  41.   
  42. extern   PACKAGE   TForm1   *Form1;     
  43.   
  44. //---------------------------------------------------------------------------     
  45.   
  46. #endif     
  47.   
  48.     /*unit1.cpp*/     
  49.   
  50. //---------------------------------------------------------------------------     
  51.   
  52.     #include        
  53.   
  54. #pragma   hdrstop     
  55.   
  56.     #include   "Unit1.h "     
  57.   
  58. //---------------------------------------------------------------------------     
  59.   
  60. #pragma   package(smart_init)     
  61. #pragma   resource   "*.dfm "     
  62.   
  63. TForm1   *Form1;     
  64.   
  65. //---------------------------------------------------------------------------     
  66.   
  67. __fastcall   TForm1::TForm1(TComponent*   Owner)     
  68.         :   TForm(Owner)     
  69. {     
  70.         ListView1-> OwnerData   =   true;     
  71.         const   int   iListViewCount   =   5000;     
  72.         ListView1-> Items-> Count   =   iListViewCount;         //必须指定,以使ListView知道其虚拟数据量   
  73.       //保存数据     
  74.         for(int   i   =   0;   i   <   iListViewCount;   ++i)   {     
  75.                 ListViewData   *plvData   =   new   ListViewData;     
  76.                 plvData-> Caption   =   "Caption "   +   AnsiString(i);     
  77.                 plvData-> SubItems1   =   "SubItems1 "   +   AnsiString(i);     
  78.                 plvData-> SubItems2   =   "SubItems2 "   +   AnsiString(i);     
  79.                 plvData-> SubItems3   =   "SubItems3 "   +   AnsiString(i);     
  80.                 m_lvDataVector.push_back(plvData);           //向vector中添加一项     
  81.         }     
  82. }     
  83.   
  84. __fastcall   TForm1::~TForm1()     
  85. {     
  86.         int   iCount   =   ListView1-> Items-> Count;     
  87.         for(int   i   =   0;   i   <   iCount;   ++i)   {     
  88.                 ListViewData   *plvData   =   m_lvDataVector[i];     
  89.                 delete   plvData;         //释放数据占用的资源     
  90.         }   
  91.         m_lvDataVector.clear();     //清空vector中所有条目     
  92. }     
  93.   
  94. //---------------------------------------------------------------------------     
  95.   
  96. //ListView在要显示某条数据时会调用这个函数   
  97.   
  98. void   __fastcall   TForm1::ListView1Data(TObject   *Sender,   TListItem   *Item)     
  99. {     
  100.         if(Item-> Index   >   m_lvDataVector.size())     
  101.                 return;     
  102.         ListViewData   *plvData   =   m_lvDataVector[Item-> Index];   
  103.       //指定要显示的条目的数据     
  104.         Item-> Caption   =   plvData-> Caption;     
  105.         Item-> SubItems-> Add(plvData-> SubItems1);     
  106.         Item-> SubItems-> Add(plvData-> SubItems2);     
  107.         Item-> SubItems-> Add(plvData-> SubItems3);     
  108. }  

速度很快,5000条数据只要1秒左右.

在使用Virtual   ListView方式时,如果要对数据排序,只需对你保存的内部数据(这里时vector对象)排序,然后ListView-> Refresh()即可。这时你在ListView中看到的数据就是排好序的数据了。

2002-12-12     大白鲨

三、

300分求解决listview大量数据添加慢的方法  (CSDN-CSDN社区-Delphi-VCL组件开发及应用 ):

--> 3楼  fei19790920 (饭桶超人II) :

标题:   让ListView更快的显示数据  
关键字:   Listview,Virtual,海量数据  
分类:   成功心得  
密级:   公开  
(评分:   ,   回复:   6,   阅读:   312)   ??  
最近刚刚完成一个项目,用Listview取代难看的DBGrid显示数据。在我 的机器上运行正常。一切看起来还不错,但是,且慢。在用户那里用实际数据一显示,我当场晕倒。天哪,区区4000条记录,居然显示了2分钟32秒……
经 过试验,发现Listview在插入1000条记录时速度尚可忍受,然后插入速度逐渐变慢。随着记录数的增加,速度越来越慢。
怎么办?使用第三 方控件?
正在彷徨无计之际,CSDN和大富翁上的相关帖子让我受到启发。对,就用Virtual模式。
首先研究大家提到的一个 Delphi自带的例子,就是{$DELPHI}\Demos\Virtual   Listview文件夹下的那个工程。
让Listview 进入Virtual模式其实很简单。设置Listview的OwnerData属性为True,然后设置Listview.Items.Count的值, 最后在Listview的OnData事件处理方法中给指定Index的Item提供Caption、SubItems等信息即可。
当然,你需 要自己管理你要显示的数据。我使用了一个TList类,当然也可以使用数组。
以上是我在自己重新编写的Demo中观察到的。但是,当我依照此思 路将其运用到我的项目中时,发现当鼠标在屏幕上移动的时候,Listview本身不停的闪烁,根本无法工作。这是怎么回事?
我在网上寻寻觅觅, 但迟迟找不到答案。也动过在大富翁和CSDN上询问的念头,但是又不甘心。
察看TListView的源码,除了看到OnData实际上由系统 LVN_GETITEMINFO消息触发外,没有任何可用信息。
仔细对比我写的Demo、Delphi自带的例程和我的项目代码,发现一点重大 的不同。那就是,前两者在Ondata事件处理方法中Item.SubItems是用Add方法添加的,而我的项目中是直接给 Item.SubItems.CommaText赋值。难道是因为这一点?我作了一些修改,呵呵,大功告成!
经过实测,现在显示4000条复杂 纪录只需区区30秒,而这时间主要是花费在数据库(我们的表结构确实存在问题)查询上,相信如果数据库结构得以优化,显示4000条记录需时绝不会超过 10秒。
至此,问题得到解决。相信许多正在苦苦寻觅第三方控件的朋友能够由此得到一些启发

-->  4楼   fei19790920 (饭桶超人II) :

  1. {用 ListView处理显示百万以上的数据,如果用传统的方法,即使使用BeginUpdate,EndUpdate,速度也远远不能满足要求,这个时候就 要使用ListView的OwnerData功能了!OwnerData允许使用一个Vitual   ListView和内存中的数据对应,我们只要在 OnData中返回数据即可。  
  2.  
  3. OnData有一个参数Item,其中Item.Index就是第N项需要显示的数据!  
  4.  
  5. 另外还可以利用OnDataHint,当数据发生变化的时候,进行的 处理。具体的请参考Delphi的Demo   VirtualListView。注意,一定要设置ListView.Items.Count属性,否则 不会显示数据。  
  6. }   
  7. //上面是猛料的   
  8. /////////////////////////////////////////////   
  9.   
  10. 事例:   
  11.   
  12. 1。     listview 的ownerdata为true;   
  13.   
  14. 2。   
  15. procedure   TForm1.ListView1Data(Sender:   TObject;   Item:   TListItem);   
  16. begin   
  17.       item.caption:= '0 ';   
  18.       item.SubItems.Add( '1 ');   
  19.       item.SubItems.Add( '2 ');   
  20.       item.SubItems.Add( '3 ');   
  21.   end;         
  22. 3。   
  23. procedure   TForm1.FormCreate(Sender:   TObject);   
  24. begin     
  25.     ListView1.Columns.Clear;   
  26.     ListView1.Columns.Add.Caption   :=   'A ';   
  27.     ListView1.Columns.Add.Caption   :=   'B ';   
  28.     ListView1.Columns.Add.Caption   :=   'C ';   
  29.     ListView1.Columns.Add.Caption   :=   'D ';   
  30.     ListView1.items.count:=10;//控制总数   
  31. end;   
  32.   
  33. /////////////////////////////////你可以举一反三  
阅读(3620) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chulia200020012010-07-02 13:47:25

使用 Virtual List 技术快速列出大批量数据 http://www.2ccc.com/article.asp?articleid=3581 发现了delphi的demo: virtual listview 和 vcl: shelllistview的两个错误! http://topic.csdn.net/t/20020706/14/854659.html

chulia200020012010-07-02 13:42:16

Delphi ListView的用法(常用技巧) 作者:蓝色忧郁 http://blog.csdn.net/2004v2004/archive/2007/05/18/1614648.aspx 字体大小: 小 中 大 //增加 i := ListView1.Items.Count; with ListView1 do begin ListItem:=Items.Add; ListItem.Caption:= IntToStr(i); ListItem.SubItems.Add(' 第 '+IntToStr(i)+' 行'); ListItem.SubItems.Add('第三列内容'); end; // 按标题删除 for i:=ListView1.Items.Count-1 downto 0 Do if ListView1.Items[i].Caption = Edit1.Text then begin ListView1.Items.Item[i].Delete()

chulia200020012010-07-02 13:39:06

本人要列出一张表,表中有一万条记录,每条记录中有十列(这样共有十万个 数据)本人试用了两种方式来显示这些数据,ListView和StringGrids,再测定一 下装载数据的时间,真是不敢相信会差这么多:ListView装载全部数据要 45~50 秒,而StringGrids只要1~2秒!! 但本人想对这些显示出来的数据进行排 序,假如用ListView,只要再加一两个函数,就能对所有的排序全部搞定,而假 如使用StringGrids,则要使用大量的排序语句,这样又要浪费大量的时间。你们 说,到底使用哪一个控件,效率和速度应怎么样兼顾? 效率和速度怎么样兼 顾?ListView和StringGrids 相关解决方法:1、效率和速度怎么样兼 顾?ListView和StringGrids 推荐解答: 假如你在向LISTVIEW中添加纪录的时 候,先不刷新,速度会快很多,当全部添加完毕后在显示速度就会很快的! 2、效率和速度怎么样兼顾?ListView和StringGrids 推荐解答: 用ListView, 选择OwnerData=true;重载OnData等关联