ListView 的闪动问题 !(100分)

X

xbl

Unregistered / Unconfirmed
GUEST, unregistred user!
当向 ListView 中写入数据时,总是会闪动,就连上面设计时定义的标题头也闪动,
我试了下面的方法不行:

ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
for I := 0 to 1000 do
begin
Application.ProcessMessages;
//这里插入数据到ListView中...
end;
ListView1.Items.EndUpdate;

我还试了这样也不行:
(ListView1 放在 Panel1 上)
Panel1.DoubleBuffered := True;

有什么办法可以解决吗?
 
ListView1.DoubleBuffered := true;
 
zw84611,这样我也试过了,不行的,
闪动得实在厉害,令人无法忍受!
 
你加上了这一句,
ListView1.Items.BeginUpdate;
应该就跟ListView无关了。因为要等到listview的item加完了之后,系统才会重绘listview.
你把全部代码贴出来看看。
另外,如果你是放在panel上面的,你应该把panel的DoubleBuffered设为True,而不是listview.
listview1.items.beginupdate就是专门为了防止闪烁的。
你如果还是解决不了问题,请贴出全面代码,可能问题出在代码中。
 
是呵
我以前弄过
先调用ListView1.Items.BeginUpdate;
加了600多个Item都没闪动
 
谢谢大家的关注!
zhangkan,我上面是用 Panel1.DoubleBuffered := True!
全面的代码就比较罗索了,下面是将数据写入到 ListView 的关键部分的测试代码,
请大家帮我看看吧,昨天后来上怎么也上不了网 !
var
I: Integer;
Item: TListItem;
begin
ListView1.Items.Clear;
ListView1.Items.BeginUpdate;
for I := 0 to 1000 do
begin
Application.ProcessMessages;
Item := ListView1.Items.Add;
Item.Caption := '000';
Item.SubItems.Add('Well');
Item.SubItems.Add('Well');
Item.SubItems.Add('Well');
...
end;
ListView1.Items.EndUpdate;
end;
 
建议你用LockWindowUpdate(hLockWnd:HWND)函数,我以前在用TMEMO显示数据时,
也就是用此函数也解决的,它还是在解决LOCK后有一次刷新.不过,比不用的时候
好得多了!具体用法如下:
LockWindowUpdate(Self.handle); //锁定刷新
////....
//在此写引起闪烁的代码
///...
LockWindowUpdate(0); //解除锁定,此时系统会对所有的可视组件进行刷新
 
weitajn,我刚刚这样试了,还是不行,而且,就连 ListView 的标题也照样闪动!
唉,这到底是怎么回事呢?
 
OK,这次调试通过了,这样:
LockWindowUpdate(ListView1.handle);

ListView1.Items.Clear;
for I := 0 to 1000 do
begin
Application.ProcessMessages;
//这里插入数据到ListView中...
end;

LockWindowUpdate(0);
 
哈,刷新时用一副动画或其它控件来盖住它。
 
weitajn,这样我也试过,这样的话,其他窗体都会闪动了!你不觉得吗?

最关键的是会使 ListView 的标题闪动 (ListView1.ViewStyle := vsReport);
是不是 ListView 装载数据时一定会闪动 ?
 
ListView1.Items.BeginUpdate;

...
ListView1.Items.EndUpdate;
这样不会有问题的
 
把你“//这里插入数据到ListView中...”的代码贴出来。
你应该这样:
listview1.items[ListIndex].SubItems[0]:= inttostr(Percent)+'%';
而不宜这样:
listview1.items[ListIndex].SubItems.Text:= inttostr(Percent)+'%';
 
用LockWindowUpdate,确实会引起其它窗体的闪动.
我用的是Windows 2000 pro + d6.
如果只是不想让标题栏闪动的话,如此解决,在Clear与Items.add之间延长点时间就可以了:

var
i: Integer;
NewColumn: TListColumn;
ListItem: TListItem;
dt: DWORD;
begin
ListView.Clear;
dt := GetTickCount;
while GetTickCount - dt < 1000 do application.ProcessMessages;
with ListView do
begin
if not bInitListView then
begin
NewColumn := Columns.Add;
NewColumn.Caption := 'IP地址';
NewColumn.Width := 200;
NewColumn := Columns.Add;
NewColumn.Caption := '端口号';
NewColumn.Width := 100;
NewColumn := Columns.Add;
NewColumn.Caption := '状 态';
NewColumn.Width := 100;
bInitListView := true;
end;

for i := 0 to 1000 do
begin
ListItem := Items.Add;
ListItem.Caption := inttostr(i);
ListItem.SubItems.Add(inttostr(i));
ListItem.SubItems.Add('调试')
end;
end;
end;

对不起,以上只是我截取的部分代码,bInitListView是一个全局变量,这里没有给出定义,
它主要是判断是否需要改变标题栏.
相信你看懂应该没问题!
 
如果装入数据量很大,最好不要使用ListView
有一个VirtualTree可以实现类似的功能,适合大数据量,非常不错
 
谢谢大家的关注,我这里上网实在是太不方便了!

zw84611:
“这里插入数据到ListView中...的代码”其实就在我在上面已经说了,就是这样:
var
I: Integer;
Item: TListItem;
begin
ListView1.Items.BeginUpdate;
ListView1.Items.Clear;
for I := 0 to 1000 do
begin
Application.ProcessMessages;
Item := ListView1.Items.Add;
Item.Caption := '000';
Item.SubItems.Add('Well');
Item.SubItems.Add('Well');
Item.SubItems.Add('Well');
//...
end;
ListView1.Items.EndUpdate;
end;

weitajn:
明天我去试试,谢谢您一直关注这个问题,如果这样可以解决标题栏的闪动的话,
那么,您帮我再想想怎么使其内容也不闪动,好吗?
这个问题我已经想了很久了,可是就是得不到结果,我所查到的解决方法是:
1
ListView1.Items.BeginUpdate;
//...
ListView1.Items.EndUpdate;
2.
(ListView1 放在 Panel1 上)
Panel1.DoubleBuffered := True;
3.
LockWindowUpdate(ListView1.handle);
//...
LockWindowUpdate(0);

原本以为以上3种一任都应该可以,可是偏偏任一种都得不到预想的效果,
我实在没有一点头绪了,真是不知道如何下手!
请大家再帮我想想办法吧,在此先谢谢了!
 
我把循环改成3次,拉长 ListView ,连续点击,发现还会出现闪烁,
要是改成1000次,用上面各位大哥的方法,倒不闪!
这个问题可能由于眼睛视觉差所造成,我也是在改人家的代码。
谢谢各位的关注!
 
for I := 0 to 1000 do
begin
Application.ProcessMessages; //没必要啊,刷新那么多次消息坐什么,白白的增加负担

//...
end;
 
可以了,我也在帮人家修改代码,谢谢大家!
 
可以了,我也在帮人家修改代码,谢谢大家!
 
顶部