有没有比这更好的方法来阻止DBgrid通过耗时的更新闪烁



在下面的情况下,有人能就如何实现我想要的目标提供建议吗?(我想知道剧院是否有帮助,但以前从未使用过。)

在我的Delphi应用程序中,我有一个通过Internet针对外部MYSQL数据库运行的查询。查询结果显示在DBGrid中(最多50行)。

用户单击一个按钮进行"网络检查",然后发生以下情况。。。

  • 首先,我将数据集的一个字段(web_response)设置为空字符串,以清除DBGrid中显示的任何现有数据。

  • 然后,对于数据集中的每一行,我提取一个字段(FieldA)的值,将其传递给一个函数,并将另一个字段的值(web_response)设置为该函数的结果。

  • 函数本身使用IdHTTP使用传递的参数在不同的远程网站上执行搜索,并返回一个响应字符串。这个过程大约需要1到2秒。

我想要的效果是网格"立即"清除所有web响应字段,然后逐行将web响应字段设置为一个值,每个值都按设置显示。

下面的代码工作正常,但没有达到我需要的效果。我想知道在某个地方使用线程而不是application.processmessages是否可以改善情况。

我现在得到的效果是,网格在一两秒钟内完全空白,然后再次出现,web响应列为空白。然后,这些行以大约每1秒一行的速度用网络响应进行更新,但每次添加新的响应时,网格都会剧烈闪烁。如果线程没有帮助,有更好的方法来做我正在做的事情吗?

我目前使用的代码(更改标识符以保护无辜者)

//empty any preexisting web responses
//disable controls to stop the DBgrid flickering while we clear out existing web responses
DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := '';
MyQuery1.Next;
end;
DBGrid1.RefreshData; //show cleared grid again
DBGrid1.DataSource.DataSet.EnableControls; 
//For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
//get the web response and put into dataset
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
Application.ProcessMessages; //,'cos the loop is slow <<-- can I get rid of this and use threads?
DBGrid1.RefreshData; //show the response we just put in dataset
MyQuery1.Next;
end;

我上次接触Delphi已经7年多了,我们不允许使用数据感知组件,所以我可能在这里给了你错误的建议。但是,您似乎过于频繁地刷新网格。尤其是你正在循环刷新网格。

我建议将代码更改为:

DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := '';
MyQuery1.Next;
end;

//For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
//get the web response and put into dataset
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
Application.ProcessMessages; //,'cos the loop is slow <<-- can I get rid of this and use    threads?
MyQuery1.Next;
end;
DBGrid1.DataSource.DataSet.EnableControls; 
DBGrid1.RefreshData; //show the response we just put in dataset

您可能希望显示一个对话框,说明正在处理,而在完成所有操作之前不显示网格。如果内存合适的话,您可能需要查看DBGrid.BegingUpdate()和DBGrid.EndUPdate()。

我只会将进度条与progressbar1.repait一起使用;在循环中只刷新进度,而不是application.prrocessmessages;

DBGrid1.DataSource.DataSet.DisableControls;
MyQuery1.First;
while not MyQuery1.Eof do
begin
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := '';
MyQuery1.Next;
end;
DBGrid1.DataSource.DataSet.EnableControls; 
DBGrid1.RefreshData; 
Application.ProcessMessages;
//For each row, check FieldA on the web and show response
MyQuery1.First;
while not MyQuery1.Eof do
begin
DataToCheck := MyQuery1.FieldByName('FieldA').AsString ; //get data to check
//get the web response and put into dataset
MyQuery1.Edit;
MyQuery1.FieldByName('web_response').AsString := GetWebCheckResponse(DataToCheck);
MyQuery1.Next;
DBGrid1.RefreshData;
Application.ProcessMessages;
end;

干杯,Pham

最新更新