2013-11-28 15 views
-1

我有一个搜索字段,用户搜索每个输入的字符。所以没有搜索按钮。问题是搜索速度很慢。我的想法是在每个键输入一点后延迟搜索,所以如果用户快速输入搜索字符串,则不用搜索就可以进行搜索。然后执行搜索。我的代码到目前为止。如何搜索每一个性能更好的字符?

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是延时为1000ms的TTimer。 IsSearching是一个布尔属性。

这是用户停止编写搜索时无法使用的代码。 这怎么能改进?

+0

您可能会拦截Char(13)以根据需要进行搜索。您可以重置OnKeyup中的计时器(disbled/enabled),并处理OnTimer内的计时器搜索和禁用。 – bummi

+0

对于那个搜索编辑,我会写一个组件['像这样'](http://pastebin.com/45Z2d7pE)。它考虑到了任何变化,而不仅仅是当用户在键盘上键入时(您应该考虑像通过弹出菜单粘贴文本等情况)。 – TLama

回答

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; 
+0

顺便说一句。罗兰,你有没有想过当用户输入一些东西,然后通过鼠标通过上下文菜单从剪贴板粘贴文本的情况?这会导致在用户停止写入并超时后搜索到文本,但在编辑框中将从剪贴板粘贴文本。我真的更喜欢使用更改事件。 – TLama

5

最根本的问题是,你的搜索是同步的,并阻塞UI。添加延迟并没有真正的帮助。用户获得反馈只需要更长的时间。

你需要做的是异步执行搜索。例如把它放在另一个线程中。搜索完成后,发信号通知主线程,以便显示结果。如果用户在搜索完成之前键入,则应使用更新后的搜索词重新开始搜索。

此方法为您提供响应式UI并尽快提供搜索结果。

注意:我假设,没有理由让你想避免反复搜索。如果搜索成本很高,那么绝对不希望在输入时实现搜索。

+1

是的,你会得到一个负责任的用户界面,但你会打扰搜索的来源(想想远程请求)与绝对每一个改变你键入...用户会很高兴,但服务器将受到影响。只有我会实施这种延迟的情况。当然,使异步搜索是必须的.​​.. – TLama

+1

@TLama是的,我甚至没有预料到搜索可能是昂贵的,应该配给。我没有考虑到这一点,因为它似乎与您输入时的搜索不符。我添加了一些文字来澄清。 –

+0

搜索的执行使其无法从主线程移动。 –

相关问题