View Full Version : سوال: تعریف event برای متغیر
Mask
شنبه 24 مهر 1389, 17:16 عصر
با سلام
من یه متغیر به نام s از نوع string تعریف میکنم.
چطوری در OnChange این متغیر میشه دستور نوشت.
Felony
شنبه 24 مهر 1389, 19:44 عصر
Wow !
متغییر که Event نداره ، اگر میخواین وقتی متن داخل متغییر رشته ای تغییر کرد متوجه بشید میتونید تو یه تایمر این مقایسه رو انجام بدید ، یا یک کلاس برای این کار بنویسید .
BORHAN TEC
شنبه 24 مهر 1389, 20:19 عصر
با سلام
من یه متغیر به نام s از نوع string تعریف میکنم.
چطوری در OnChange این متغیر میشه دستور نوشت.
یک کلاس تعریف کنید و در آن یک فیلد رشته ای تعریف کنید(در قسمت private) . سپس برای آن یک property ایجاد کنید. در روالی که مربوط به قسمت write پروپرتی است می توان یک شرط را قرار داد که در صورت تغییر مقدار فیلد رشته ای مثلاً یک کد اجرا شود(مثل یک تابع)!!!
Felony
شنبه 24 مهر 1389, 20:44 عصر
یک کلاس تعریف کنید و در آن یک فیلد رشته ای تعریف کنید(در قسمت private) . سپس برای آن یک property ایجاد کنید. در روالی که مربوط به قسمت write پروپرتی است می توان یک شرط را قرار داد که در صورت تغییر مقدار فیلد رشته ای مثلاً یک کد اجرا شود(مثل یک تابع)!!!
این هم یه نمونه کد :
type
TMyClass= class
private
procedure SetString(const Value: String);
property Str: String write SetString;
end;
procedure TMyClass.SetString(const Value: String);
begin
ShowMessage(Value);
end;
استفاده :
var
Test: TMyClass;
begin
Test:= TMyClass.Create;
try
Test.Str:= 'Sample Text';
finally
Test.Free;
end;
end;
Mahmood_M
شنبه 24 مهر 1389, 20:47 عصر
با همون Write احتمالا مشکلتون حل میشه ولی برای اینکه با Event ها بهتر آشنا بشید :
برای یک متغیر نمی تونید Event در نظر بگیرید ! ، Event درواقع یک Procedure هست و خودبخود اجرا نمیشه ، بلکه باید در یک Procedure دیگه اون رو فراخوانی کنید ، به عنوان مثال فرض کنید کلاسی به صورت زیر تعریف کردیم :
type
TMyClass = class
private
MyString : String;
public
OnMyEvent : TNotifyEvent;
procedure SetString(S : String);
procedure GetString(var S : String);
end;
کلاس بالا یک عضو String داره به همراه دو Procedure که وظیفه ی نوشتن و خواندن از عضو String یعنی MyString رو دارن ، برای کلاسمون یک Event هم در نظر گرفتیم ، عضوی با نام OnMyEvent و از نوع TNotifyEvent ، نوع TNotifyEvent به صورت زیر تعریف میشه :
TNotifyEvent = procedure(Sender: TObject) of object;
همونطور که مشاهده می کنید ، TNotifyEvent هم یک Procedure هست ، البته شما آزادید که از نوع TNotifyEvent استفاده نکنید و Procedure دلخواه خودتون رو با ورودیهای دلخواه تعریف کنید ...
خوب ، میخوایم تغییر MyString رو به کاربر اطلاع بدیم ، برای ثبت مقدار در MyString از Procedure ای با نام SetString که در بدنه ی کلاسمون تعریف کردیم استفاده میکنیم ، پس توی همین Procedure باید مقدار وارد شده و مقدار موجود در MyString رو مقایسه کنیم و در صورت وجود اختلاف ، مقدار جدید رو در MyString قرار بدیم و همچنین OnMyEvent رو اجرا کنیم ، ابتدا Procedure ها رو تعریف می کنیم :
procedure TMyClass.GetString(var S: string);
begin
S := MyString;
end;
procedure TMyClass.SetString(S: string);
begin
if S <> MyString then
begin
if Assigned(OnMyEvent) then
OnMyEvent(Self);
MyString := S;
end;
end;
به تعریف SetString توجه کنید ، در این Procedure ابتدا اختلاف رشته ی وارد شده و رشته ی موجود رو مقایسه می کنیم ، در صورت وجود اختلاف اول چک می کنیم که Procedure ای برای OnMyEvent درنظر گرفته شده یا نه ، اگر در نظر گرفته شده باشه ، اون رو اجرا میکنیم و در نهایت هم مقدار جدید رو در MyString قرار میدیم ...
برای اختصاص دادن Procedure به OnMyEvent هم میتونید مثلا یک Procedure به صورت زیر در قسمت Public فرم تعریف کنید و بعد اون رو به OnMyEvent اختصاص بدید :
type
TForm1 = class(TForm)
...
private
{ Private declarations }
public
procedure MyEvent(Sender : TObject);
{ Public declarations }
end;
و
begin
M := TMyClass.Create;
M.OnMyEvent := Form1.MyEvent;
...
end;
نتیجه گیری : برای اجرای یک Event باید یک Procedure به عنوان Event و یک Procedure هم به عنوان اجراکننده و صدا زننده ی Event تعریف بشه ، به عنوان یک مثال دیگه فرض کنید می خواید یک کرنومتر بسازید که متد Start داره و می خواید در زمان Start شدن اون رویدادی رو اجرا کنید ، در این صورت کلاستون مثلا باید یک Procedure برای Start و یک Procedure هم برای مثلا OnStart داشته باشه و در متد Start هم باید OnStart رو فراخوانی کنید ...
یک مثال ساده هم ضمیمه کردم ...
موفق باشید ...
BORHAN TEC
شنبه 24 مهر 1389, 21:48 عصر
اگه کدی که جناب مجتبی تاجیک قرار دادند رو به شکل زیر بنویسید بهتره:
type
TMyClass = class
private
FStr: String;
procedure SetStr(const Value: String);
published
property Str: String read FStr write SetStr;
end;
procedure TMyClass.SetStr(const Value: String);
begin
if Value <> FStr then
begin
DoSomething;
FStr := Value;
end;
end;
Felony
یک شنبه 25 مهر 1389, 07:05 صبح
اگه کدی که جناب مجتبی تاجیک قرار دادند رو به شکل زیر بنویسید بهتره:
type
TMyClass = class
private
FStr: String;
procedure SetStr(const Value: String);
published
property Str: String read FStr write SetStr;
end;
procedure TMyClass.SetStr(const Value: String);
begin
if Value <> FStr then
begin
DoSomething;
FStr := Value;
end;
end;
من کد رو به اون صورت نوشتم تا نیازی به ست کردن متغییر به وسیله یه تابع داخل کلاس نباشه و مستقیم بشه متغییر رو تغییر داد ، اگر قرار به بررسی صحت تغییر رشته باشه در این مورد بهتره کلاس اینطور نوشته بشه که از لحاظ کپسوله سازی هم مشکلی پیش نیاد :
type
TMyClass= class
strict private
MyStr: String;
function GetString: String;
procedure SetString(const Value: String);
private
property Str: String read GetString write SetString;
end;
function TMyClass.GetString: String;
begin
Result:= MyStr;
end;
procedure TMyClass.SetString(const Value: String);
begin
if Value <> MyStr then
begin
ShowMessage(Value);
MyStr := Value;
end;
end;
اینجوری نیازی به صدا زدن یک تابع از داخل کلاس نیست که کار ست کردن متغییر رشته ای رو انجام بده . کافیه مستقیم خود متغییر رشته ای مورد نظر تغییر پیدا کنه :
var
Test: TMyClass;
begin
Test := TMyClass.Create;
try
Test.Str:= 'Sample Text';
finally
Test.Free;
end;
end;
BORHAN TEC
یک شنبه 25 مهر 1389, 12:10 عصر
من کد رو به اون صورت نوشتم تا نیازی به ست کردن متغییر به وسیله یه تابع داخل کلاس نباشه و مستقیم بشه متغییر رو تغییر داد ، اگر قرار به بررسی صحت تغییر رشته باشه در این مورد بهتره کلاس اینطور نوشته بشه که از لحاظ کپسوله سازی هم مشکلی پیش نیاد :
چه فرقی کرد؟؟؟؟
خوب اگه این کلاس در یک یونیت دیگه تعریف شده باشه مگه میشه از property مربوط به Str استفاده کرد. اگه کد رو بخواهیم که به نحو بهتری تعریف کنیم باید قبل از اعلان Property کلمه class را قرار دهیم. با این کار دیگر نیازی به نوشتن خط زیر نیست:
Test := TMyClass.Create;
موفق باشید...
Felony
یک شنبه 25 مهر 1389, 12:43 عصر
چه فرقی کرد؟؟؟؟
از لحاظ کلی و مفهومی تفاوتی نداره ، فرقش زمانی هست که قرار باشه از این کلاس در یونیت جاری استفاده بشه و قوانین کپسوله سازی رعایت بشه ، در این صورت کد اولی که شما گزاشتید کپسوله نیست و اگر کلاس در یونیت فعلی ایجاد شده باشه میشه به Private دسترسی داشت که من به Strict Private تغییرش دادم تا در یونیت جاری هم نشه به اجزای private دسترسی داشت ، ولی اگر قرار باشه تو یونیت دیگه استفاده بشه هر دو کد یکسان هستند .
* البته در مورد استفاده در ینویت دیگر هم کافیه Private رو به Published که شما در کدتون نوشتید یا Public تغییر داد تا Str به صورت یک اعلان عمومی در بیاد و در دیگر یونیت ها مشاهده بشه .
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.