من میخوام در یک حلقه for یک کامپوننت رو به تعداد creat ، n کنم . چه کدی بنویسم ؟
من میخوام در یک حلقه for یک کامپوننت رو به تعداد creat ، n کنم . چه کدی بنویسم ؟
درود
با کد زیر میتونید 10 تا Instance از کلاس TButton بسازید:
procedure TForm1.Button1Click(Sender: TObject);
var
iCounter: Integer;
iTop: Integer;
begin
iTop := 50;
for iCounter := 1 to 10 do
begin
with TButton.Create(Self) do
begin
Name := 'Btn_' + IntToStr(iCounter);
Caption := ' Button #' + IntToStr(iCounter);
Parent := Form1;
Left := 100;
Top := iTop;
Inc(iTop, 30);
end;
end;
end;
فقط Destroy کردن Object هایی که ساخته شده رو (در صورت عدم نیاز) فراموش نکنید.
ممکنه بگید چطور و چه وقت destroy کنم ؟
کسی نیست جواب بده ؟
زمانی که دیگه نیازی به Object ها نداشتید میبایست اونها رو Destroy کنید تا حافظه تخصیص یافته ازاد بشه،
برای این کار هم میتونی از ObjectName.Free استفاده کنی.
فلويد گواهي مي دهد به آنکه زيستن در هنگامهی استبداد، چه آسان روياها را واژگون مي کند، چه سهل بر چهرهی آزادی تيغ میکشد!
من object ها رو در یک حلقه for ایجاد کردم و حالا برای free کردنشون باید از یک حلقه for دیگه استفاده کنم ولی نمیدونم چطور به object های ایجاد شده دسترسی داشته باشم .
ممکنه بگید دقیقاً چه کدی بنویسم ؟
از خصوصیت Name اون کامپوننت ها استفاده کن
Form1.FindComponent('Btn' + IntToStr(iCounter)).Free;
سلام
من هم یک نظری میدهم، اگر اشکال داشت لطفا بگویید:
هنگامی که ما از طریق کدنویسی یک کامپوننت به فرم خود میافزاییم و Owner آن را فرم خود قرار میدهیم (مانند فوق) حتی اگر آنها را خودمان Destroy نکنیم، هنگامی که فرم Destroy میشود خودش آنها را Destroy میکند. هر چند که تاکید بر این است که خودمان این کار را انجام بدهیم.
نکته بعد اینکه قبل از Destroy کردن یک کامپوننت باید با فراخوانی متد RemoveComponent و ارسال نام کامپوننت خود به آن، آن را از لیست کامپوننتهای فرم خارج کنیم:
RemoveComponent(ComponentName);
ComponentName.Free;
صحبت شما درسته. اما در مورد RemoveComponent نه. برای من جالبه که شما اینو از کجا باش آشنا شدین، اما نه نیازی به صدا زدن هیچی نیست. ضمنا هیچ تاکیدی هم بر Destroy کردن دستی کمپوننت نیست. (وقتی Owner داره!)
این مطلب بستگی داره به اینکه فرم شما چقدر عمر میکنه. اگه قرار باشه فرم شما به مدت طولانی عمر کنه و شما در طول این مدت نیازی به اون کامپوننت هایی که اضافه کردید، نداشته باشید، Free نکردن اون کامپوننت ها فقط منابع سیستم رو هدر میده!هنگامی که ما از طریق کدنویسی یک کامپوننت به فرم خود میافزاییم و Owner آن را فرم خود قرار میدهیم (مانند فوق) حتی اگر آنها را خودمان Destroy نکنیم، هنگامی که فرم Destroy میشود خودش آنها را Destroy میکند. هر چند که تاکید بر این است که خودمان این کار را انجام بدهیم.
هیچ لزومی به فراخوانی RemoveComponent قبل از آزاد کردن کامپوننت نیست.نکته بعد اینکه قبل از Destroy کردن یک کامپوننت باید با فراخوانی متد RemoveComponent و ارسال نام کامپوننت خود به آن، آن را از لیست کامپوننتهای فرم خارج کنیم
خب حالا بعد از این که component ها creat یا free شد آیا فقط با استفاده از خصوصیات top و left میشه موقعیت این component ها و بقیه component هایی که زیر اونها قرار گرفتند رو کنترل کرد ؟ یا اینکه روش دیگه ای هم وجود داره ؟
منظورم اینه که هر بار که این component ها creat یا free می شن ، باید خصوصیات top و left بقیه component های زیر اونها هم تغییر داده بشه؟
خیر. موقعیت کنترل ها نسبت به گوشه بالا سمت چپ کنترل والدشون (Parent) سنجیده میشه، نه نسبت به هم. تغییر مکان یک کنترل روی کنترل های دیگه تاثیری نداره.منظورم اینه که هر بار که این component ها creat یا free می شن ، باید خصوصیات top و left بقیه component های زیر اونها هم تغییر داده بشه؟
در ضمنFree کردن یک کنترل موجب از بین رفتن اون میشه و بعد از اون دیگه کنترلی وجود نداره که بخواید به خصوصیات اون دسترسی داشته باشید.
خب من هم همین رو می گم . اگه یه component در جایی creat بشه که قبلاً یک component دیگه وجود داشته ، اونوقت component جدید روی component قبلی قرار می گیره .تغییر مکان یک کنترل روی کنترل های دیگه تاثیری نداره.
من می خوام در حالت Runtime برای کامپوننت های جدید جای خالی باز کنم که روی کامپوننت های قبلی قرار نگیرند و چون تعداد کامپوننت های ایجاد شده در هر اجرا متفاوته بنابراین کنترل موقعیت کامپوننت ها باید به صورت پویا انجام بشه .
حالا می خوام بدونم فقط با خصوصیات top و left می تونم این کار رو انجام بدم یا روش دیگه ای هم هست ؟
نمیدونم تونستم منظورم رو خوب برسونم یا نه؟...
تفاوتی یا زمان Design نداره، شما اونجا میتونید یک Component رو روی Component دیگه بندازید ، به صورت RunTime
هم فرقی نمیکنه.
شما میبایست Top و Left رو تنظیم کنید.
ولی خیلی دوست دارم بدونم که چه برنامه ایی هست که Component ها رو در زمان اجرا میبایست که بسازید؟
فلويد گواهي مي دهد به آنکه زيستن در هنگامهی استبداد، چه آسان روياها را واژگون مي کند، چه سهل بر چهرهی آزادی تيغ میکشد!
من همچنان در free کردن کامپونت ها مشکل دارم .
در یک حلقه for یه سری کامپوننت creat کردم و وقتی فرم hide میشه اونها رو free می کنم ، با F7 هم trace کردم ، دقیقاً به تعداد کامپوننت های ایجاد شده عمل free انجام می شه ، ولی وقتی برای بار دوم فرم میخواد show بشه این Error رو می ده :
component ' DC1' alerady exist
DC1 اسم کامپوننتی که قبلاً creat شده .
میشه روش Free کردن رو بنویسید؟
فلويد گواهي مي دهد به آنکه زيستن در هنگامهی استبداد، چه آسان روياها را واژگون مي کند، چه سهل بر چهرهی آزادی تيغ میکشد!
با استفاده از این کد کامپوننت ها رو free می کنم :
for i:=1 to AdoQuery2.recordCount do
form9.FindComponent('DC'+inttostr(i)).Free;
که AdoQuery2.recordCount تعداد فیلدهایی رو مشخص می کنه که باید به تعداد اونها کامپوننت ایجاد بشه .
و برای creat کردن هم این کد رو نوشتم :
count:=form9.ADOQuery2.recordCount;
for i:=1 to count do
begin
groupbox1.Height:=groupbox1.Height+25;
with TDbCheckbox.create(self) do
begin
name:='DC'+inttostr(i);
caption:=ADOQuery2.FieldValues['name'];
parent:=groupbox1;
BiDiMode:=bdRightToLeft;
dataSource:=datasource2;
dataField:='name';
top:=t;
t:=t+16;
left:=90;
font.charset:=ARABIC_CHARSET;
font.Name:='Arial Black';
font.Size:=10;
checked:=false;
end;
ADOQuery2.Next;
end;
روش فعلیتان کلا خیلی جالب نیست.
پیشنهاد می کنم یک لیست از نوع TComponentList بسازید و همه کامپوننت ها را پس از اینکه create کردید به آن اضافه کنید. سپس صدا زدن متد Clear همین شی لیست؛ به سادگی کلیه کامپوننتهایی که درون آن هستند را free می کند.
ضمنا لیست مزبور در یونیت Contnrs تعریف شده است.
میشه بیشتر توضیح بدید لطفاً .
چطور از TComponentList استفاده کنم ...
جناب نفیسی ، clear برای تخریب لیست کامپوننتها نیست.
شما وقتی کنترلهایی را به فرمتان اضافه میکنید (با استفاده از InsertControl) هندل آنها در Controls وجود خواهد داشت که با یک دستور ساده میتوانید تمامی آنها را تخریب نمایید:
while controlCount>0 do
Controls[0].Free;
... چه بگویم که غم از دل برود چون تو بیایی
من بالاخره چطور از TComponentList استفاده کنم
مشکلم حل شد
خب الحمد لله. (نمی دونم بالاخره از TComponentList استفاده کردین یا نه؟)
در پاسخ به جناب hr110 هم باید بپرسم که از کجای جمله چنین برداشت می شه که clear شی TComponentList رو تخریب می کنه؟ شایدم منظورتون اینه که کمپوننتهای درون لیست رو تخریب نمی کنه؟
لازم به توضیحه که:
متد clear کلیه اشیا داخل لیست را از آن حذف کرده و در نتیجه همگی تخریب نیز می شوند. (البته اگر OwnsObjects مقدار "درست" داشته باشد)
اما خود TComponentList مسلما و همانند تمامی اشیای دیگر، باید با صدا زدن متد Free تخریب شود.
لطفاً راهنمای دلفی را مجدداً مطالعه نمایید.متد clear کلیه اشیا داخل لیست را از آن حذف کرده و در نتیجه همگی تخریب نیز می شوند.
... چه بگویم که غم از دل برود چون تو بیایی
من با وجود اطمینان صد در صد و یقین مطلقی که به صحبت خودم داشتم، دلفی را بازکردم و صحبت خودم را امتحان کردم. (و همونطور که قبلا هم گفته ام از اینکه وسط کار با اینترنت دلفی رو باز کنم، اونهم وقتی کوچکترین سودی برایم نداره، واقعا متنفرم)
به شما دوست عزیز هم جدا توصیه می کنم که قبل از اینکه به کسی پیشنهاد کنین مثلا راهنمای دلفی رو بخونه، (اگر تجربه کافی در دلفی ندارین) حداقل به خودتون زحمت یکبار تجربه کردن رو بدین. واقعا آدم از تجربه کردن ضرر نمی کنه.
-------------------
در نهایت برای مفید بودن این صحبت برای سایر دوستان، باید بگم که آنچه در مورد متد clear نوشتم کاملا صحیح است. (امتحان کنید یا سورس کامپوننت را با دقت بخوانید)
سلام؛
جناب نقیسی حق با شما بود، متد clear علاوه بر حذف آیتمها ، حافظه گرفته شده را نیز به سیستم برمیگرداند.
عذر خواهی مرا بپذیرید.
... چه بگویم که غم از دل برود چون تو بیایی
با سلام
روشی تعریف event برای کامپوننتهای ایجاد شده در برنامه چگونه می باشد .
با تشکر