PDA

View Full Version : مشکل در جستجو توسط اديت باکس



yalameh
دوشنبه 19 دی 1390, 17:25 عصر
سلام دوستان .
مشکلي بر روي سرچ در بانک اطلاعاتي برخورد کرده ام . ممنون ميشم اگه راهنمائي کنيد
يک edit در برنامه دلفي دارم که کاربر بر اساس مقدار آن در بانک اطلاعاتي سرچ مي کند . در onchange اديت ، کوئري سرچ نوشته شده . وقتي که کاربر بخواد بر اساس کلمه خاصي سرچ کنه با زدن هر کليد يکبار عمل جستجو را انجام مي ده و اين قضيه باعث پائين آمدن سرعت جستجو مي شه . راهي وجود داره که کاربر وقتي کلمه خودشو به اتمام رسوند عمل سرچ انجام بشه مثلا اگر يک ثانيه کليدي زده نشد اون موقع کوئري انجام بشه .
ممنون

Mahmood_M
دوشنبه 19 دی 1390, 17:32 عصر
بهتره جستجو رو در OnKeyPress مربوط به Edit مدیریت کنید ، مثلا اگر کلید Enter زده شد ، جستجو انجام بشه ، یا اینکه یک دکمه کنار Edit بزارید برای شروع عملیات جستجو

yalameh
سه شنبه 20 دی 1390, 08:57 صبح
ولي برنامه حالتي داره که حتما بايد بصورت اتوماتيک سرچ را انجام بده . بدون زدن اينتر يا کليد خاصي .

BORHAN TEC
سه شنبه 20 دی 1390, 09:25 صبح
راهي وجود داره که کاربر وقتي کلمه خودشو به اتمام رسوند عمل سرچ انجام بشه مثلا اگر يک ثانيه کليدي زده نشد اون موقع کوئري انجام بشه .

راه که همیشه وجود داره، به عنوان مثال می توانید از کدی به شکل زیر استفاده کنید، ولی در این روش در صورتی که حجم داده ها زیاد باشد بهتر از که از قبل بر روی فیلدی که عمل SELECT را روی آن انجام می دهید Index بگذارید :متفکر:که سرعت اجرای Query بالا برود، تا با مشکلات کمتری مواجه شوید:

unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Timer1: TTimer;
Label1: TLabel;
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
// Look At This
new: Cardinal;
old: Cardinal;
const
OneSecond = 1000;
/// ///////////
implementation
{$R *.dfm}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
old := GetTickCount;
Timer1.Enabled := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled := False;
Timer1.Interval := 100;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
new := GetTickCount;
// One Second
if (new - old) >= OneSecond then
begin
Timer1.Enabled := False;
Label1.Caption := 'Runing Query'; // or Execute a SELECT Query
Exit;
end;
end;
end.

همانطور که می بینید با کد بالا حجم کد نویسی شما تا حدی بالا می رود که این کار زیاد جالب نیست. پیشنهاد می کنم برای استفاده از این تکنیک خودتان یک کامپوننت بسازید. توجه داشته باشید در کلاس مربوط به کامپوننتی که (احتمالاً) خواهید ساخت باید یک فیلد از نوع TTimer وجود داشته باشد. به عنوان نمونه می توانید از کامپوننت مثال TFlashingLabel در فصل 20 مربوط به کتاب Sam's Teach yourself Borland Delphi 4.0 in 21 Days (Updated for Version 5) ایده بگیرید.

mohsen24000
سه شنبه 20 دی 1390, 10:03 صبح
بخاطر ورژن دلفی XE و یا XE2

BORHAN TEC
سه شنبه 20 دی 1390, 10:08 صبح
بخاطر ورژن دلفی XE و یا XE2
بخاطر XE نیست، بخاطر اینه که من این کد رو در Delphi XE2 نوشته ام. البته اگه شما اسم یونیت ها رو در Delphi XE2 مثل نسخه های قدیمی دلفی هم بنویسید به جز چند مورد واقعاً خاص! با هیچ مشکلی مواجه نخواهید شد.

AMIBCT
سه شنبه 20 دی 1390, 11:43 صبح
راه خیلی ساده:

یک Timer برای شروع جستجو ایجاد کنید و کدهای جستجو رو داخلش بنویسید
Enabled اون رو False تعیین کنید
قبل از جستجو در Timer کد بنویسید که Enabled رو False کنه
در فیلد جستجو با هر بار تغییر یک بار Timer رو غیرفعال و فعال کنید
زمان تعیین شده برای Timer زمان انتظار رو مشخص می‌کنه

یعنی کاربر اگر بین تایپش بیشتر از زمان مشخصی فاصله بیفته Timer فعال می‌شه، جستجو می‌کنه و خودش رو غیرفعال می‌کنه

yalameh
سه شنبه 20 دی 1390, 12:55 عصر
با تشکر از تمام دوستان . بعد از کلي سرچ کد زير را پيدا کردم . شبيه راه حل AMIBCT است . مشکلم حل شد . دوستان نظر خاصي روي کد زير ندارند :



procedure TForm1.Edit1Change(Sender: TObject);
begin
timer1.Enabled := False;
timer1.Enabled := True;
end;

//The timer is DoFind interval 150

procedure TForm1.Timer1Timer(Sender: TObject);
begin
timer1.Enabled := False;
Companies.Locate('_Name', Finder.Text, [loCaseInsensitive, loPartialKey]);
end;

BORHAN TEC
سه شنبه 20 دی 1390, 13:44 عصر
کد خوبیه، ولی باید کمی بهینه تر بشه. برای بهینه سازی اون میتونید از کدی مثل زیر استفاده کنید:

unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
Label1: TLabel;
Edit1: TEdit;
procedure Timer1Timer(Sender: TObject);
procedure Edit1Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
I: Integer;
old, New: string;
implementation
{$R *.dfm}
procedure TForm1.Edit1Change(Sender: TObject);
begin
Timer1.Enabled := False;
New := Edit1.Text;
Timer1.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if old = New then
begin
Timer1.Enabled := False;
Exit;
end;
Timer1.Enabled := False;
InC(I); // Or Execute Query
Label1.Caption := IntToStr(I);
old := New;
end;
end.
البته بهتره که Interval مربوط به Timer رو هم افزایش بدین، به عنوان مثال 1500 میلی ثانیه.