我有一个搜索字段,用户搜索每个输入的字符。所以没有搜索按钮。问题是搜索速度很慢。我的想法是在每个键输入一点后延迟搜索,所以如果用户快速输入搜索字符串,则允许不搜索。然后执行搜索。我的代码到目前为止。
procedure TAgreementModuleForm.SetIsSearching(const Value: Boolean);
begin
fIsSearching := Value;
tmrDelayKey.Enabled := Value;
end;
procedure TAgreementModuleForm.tmrDelayKeyTimer(Sender: TObject);
begin
IsSearching := True;
end;
procedure TAgreementModuleForm.txtSearchAgreementCustomerExit(Sender: TObject);
begin
IsSearching := False;
end;
procedure TAgreementModuleForm.txtSearchAgreementCustomerKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
var
vSearchExpression: string;
begin
if IsSearching then
begin
vSearchExpression := Trim(txtSearchAgreementCustomer.Text);
IsSearching := False;
if vSearchExpression <> '' then
DoSearch(vSearchExpression);
end
else
tmrDelayKey.Enabled := True;
end;
tmrDelayKey是一个延迟为1000毫秒的TTimer。 IsSearching是一个布尔属性。
这不是工作代码,因为用户停止编写搜索。 如何改进?
答案 0 :(得分:5)
根本问题是您的搜索是同步的并且阻止了UI。添加延迟并没有多大帮助。用户获取反馈需要更长的时间。
您需要做的是异步执行搜索。比如把它放在另一个线程中。搜索完成后,发出主线程信号,以便显示结果。如果用户在搜索完成之前键入,则应使用更新的搜索词重新开始搜索。
此方法可为您提供响应式用户界面,并尽快提供搜索结果。
注意:我假设您没有理由避免重复搜索。如果搜索成本很高,那么您绝对不希望在键入时实现搜索。
答案 1 :(得分:2)
我相信这段代码应该有效:
var SearchComplete: Boolean;
procedure TForm1.DoSearch(Astring: String);
begin
SearchComplete:= True;
txtSearchAgreementCustomer.Text := 'Searched: '+Astring;
end;
procedure TForm1.tmrDelayKeyTimer(Sender: TObject);
begin
if not SearchComplete then
begin
DoSearch(txtSearchAgreementCustomer.Text);
end;
end;
procedure TForm1.txtSearchAgreementCustomerKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
var C: Char;
begin
C:= Char(Key);
if (C in ['a' .. 'z']) or (C in ['A' .. 'Z']) or (C in ['0'..'9']) then
SearchComplete := False;
end;
procedure TForm1.txtSearchAgreementCustomerExit(Sender: TObject);
begin
tmrDelayKey.Enabled := False;
end;
procedure TForm1.txtSearchAgreementCustomerEnter(Sender: TObject);
begin
tmrDelayKey.Enabled := True;
SearchComplete := True;
end;