假設在panel1上動態產生3個button,這時如可取得某個button的caption值? |
答題得分者是:pedro
|
mitchellhu
一般會員 發表:23 回覆:53 積分:15 註冊:2007-06-12 發送簡訊給我 |
假設在panel1上動態產生3個button,這時如可取得某個button的caption值?
我曾試著先用panel1.Controlcount 取得目前panel1上已有幾個元件(因為panel1上的元件只有button,所以直接計算元件數)。若目前動態產生了3個button(應該是panel1.contorls[0],panel1.contorls[1],panel1.contorls[2],分別代表button1,button2,button3)。接著我又設定一個string變數BName想來取得第一個Button的Caption. 在設件期部份code如下: var Bname : string; begin Banme := panel1.Controls[0].caption; end; 這段code在設計期ok,但編譯時報錯[DCC Error] Unit1.pas(59): E2362 Cannot access protected symbol TControl.Caption 按f1查hlep, Caption真的是TContol的一項protected porperty。 因為pane1上的button都是動態產生的,設計期無得知確實的button數量,所以只能用panel1來間接取得這些button的訊息,但從錯訊息看來好像無法不去處理TControl的porteced member的問題,請教前輩們這當如何處理,才不會違反這個原則? 另要讓其它元件的Caption設定成第一個buttn的Caption,該如何處理? 我原本直覺想法是 panel2.Control[0].caption := panel1.Controls[0].caption 看起是完全不可能了,請問如何解決呢? 編輯記錄
|
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
|
Coffee
版主 發表:31 回覆:878 積分:561 註冊:2006-11-15 發送簡訊給我 |
|
wameng
版主 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
你只要自己Keep TButton Array 就可以直接存取它.
<textarea class="delphi" rows="10" cols="60" name="code"> unit TestMain; interface uses Windows, Forms, Controls, StdCtrls, Classes, Dialogs, ExtCtrls; type TButtons = array of TButton; TForm1 = class(TForm) Panel1: TPanel; CreateBtns: TButton; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure CreateBtnsClick(Sender: TObject); procedure Panel1Resize(Sender: TObject); private Buttons: TButtons; procedure DO_BUTTON_CLICK(Sender: TObject); function GET_BTN_BOUNDSRECT(Index: Integer): TRect; public function CreateButtons(var A: TButtons; Count: Integer): Boolean; procedure DestroyButtons(var A: TButtons); end; var Form1: TForm1; implementation {$R *.dfm} uses SysUtils, Math; { TForm1 } function TForm1.CreateButtons(var A: TButtons; Count: Integer): Boolean; var I: Integer; begin DestroyButtons(A); SetLength(A, Count); for I := 0 to Count-1 do begin A[I] := TButton.Create(nil); with A[I] do begin A[I].Tag := I; A[I].Caption := 'Btn' IntToStr(I); A[I].OnClick := DO_BUTTON_CLICK; A[I].Parent := Panel1; with GET_BTN_BOUNDSRECT(I) do A[I].SetBounds(Left, Top, Right, Bottom); A[I].Visible := True; end; end; Result := Length(A) = Count; end; procedure TForm1.DestroyButtons(var A: TButtons); var I: Integer; begin if A <> nil then begin for I := 0 to Length(A)-1 do if A[I] <> nil then FreeAndNil(A[I]); A := nil; end; end; procedure TForm1.DO_BUTTON_CLICK(Sender: TObject); begin if Sender is TButton then ShowMessage(TButton(Sender).Caption); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin DestroyButtons(Buttons); end; procedure TForm1.CreateBtnsClick(Sender: TObject); begin if CreateButtons(Buttons, 100) then Panel1Resize(Panel1); CreateBtns.Enabled := False; end; function TForm1.GET_BTN_BOUNDSRECT(Index: Integer): TRect; const BW = 70; BH = 20; var CC, C, R: Integer; begin CC := Max(1,Panel1.ClientWidth div BW); C := Index mod CC; R := Index div CC; Result := Rect(C*BW 5,R*BH 5,BW,BH); end; procedure TForm1.Panel1Resize(Sender: TObject); var I: Integer; begin CreateBtns.Left := ClientWidth - CreateBtns.Width - 10; Panel1.Width := ClientWidth - CreateBtns.Width - 20; if Buttons <> nil then for I := 0 to Length(Buttons)-1 do with GET_BTN_BOUNDSRECT(I) do Buttons[I].SetBounds(Left, Top, Right, Bottom); end; end. </textarea> |
syntax
尊榮會員 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
pedro756901 的方法,可以適用絕大部分的狀況,也不易有 bug ===================引 用 mitchellhu 文 章=================== 假設在panel1上動態產生3個button,這時如可取得某個button的caption值? 我曾試著先用panel1.Controlcount 取得目前panel1上已有幾個元件(因為panel1上的元件只有button,所以直接計算元件數)。若目前動態產生了3個button(應該是panel1.contorls[0],panel1.contorls[1],panel1.contorls[2],分別代表button1,button2,button3)。接著我又設定一個string變數BName想來取得第一個Button的Caption. 在設件期部份code如下: var Bname : string; begin Banme := panel1.Controls[0].caption; end; 這段code在設計期ok,但編譯時報錯[DCC Error] Unit1.pas(59): E2362 Cannot access protected symbol TControl.Caption 按f1查hlep, Caption真的是TContol的一項protected porperty。 因為pane1上的button都是動態產生的,設計期無得知確實的button數量,所以只能用panel1來間接取得這些button的訊息,但從錯訊息看來好像無法不去處理TControl的porteced member的問題,請教前輩們這當如何處理,才不會違反這個原則? 另要讓其它元件的Caption設定成第一個buttn的Caption,該如何處理? 我原本直覺想法是 panel2.Control[0].caption := panel1.Controls[0].caption 看起是完全不可能了,請問如何解決呢? |
mitchellhu
一般會員 發表:23 回覆:53 積分:15 註冊:2007-06-12 發送簡訊給我 |
Jow 大:
您所附的程式碼看起來考慮很完整。但我能力有限,看不太懂。 我也將你的code實作後,產生一個錯誤[DCC Error] TestMain.pas(50): E2003 Undeclared identifier: 'forbidden' 請問這是為什麼? 另一個問題想請教,因為元件是動態產生的,若使用者又再次按下CreateBtns,則一定會產生問題,因不應再產生第二次相同的Buttons。 我曾試在動態產生buttons前,檢查panel生是否有button存在,若存在則free button,但遇到了一個問題,已free的button,的name仍會存在,系統無法產生同name的button,請問free後之元件,是仍然存在記憶體中嗎?後來我用destory也是同樣的情況?請問該如何處理? 謝謝你!
編輯記錄
mitchellhu 重新編輯於 2007-08-13 11:51:19, 註解 無‧
|
danny
版主 發表:100 回覆:522 積分:595 註冊:2002-03-11 發送簡訊給我 |
那是使用 Delphi RTTI 的方式取得, 但是缺點就是不保證每一個版本的 Delphi RTTI 都一樣
你可以使用 pedro756901 的方式, 只要改 TButton 部份就可以適用其他元件, pedro756901 的方式也可以寫成如下 for i:=0 to Panel.ComponentCount-1 do if Panel.Components[i] is TButton then begin TButton(Panel.Components[i]).Caption := '123'; end 另外以上方式的順序是依元件的 TabOrder (就是你放上元件的順序), 不過 TabOrder 可以隨你高興改順序 還有 FindComponent 也可以依你指定的元件名稱, 找到你的元件 TButton(FindComponent('Button1')).Caption := '123'; ===================引 用 mitchellhu 文 章=================== Jow?大: 您所附的程式碼看起來考慮很完整。但我能力有限,看不太懂。 我也將你的code實作後,產生一個錯誤[DCC Error] TestMain.pas(50): E2003 Undeclared identifier: 'forbidden' 請問這是為什麼? 另一個問題想請教,因為元件是動態產生的,若使用者又再次按下CreateBtns,則一定會產生問題,因不應再產生第二次相同的Buttons。 我曾試先寫了一段在動態產生buttons前,檢查panel生是否有button存在,若存在則free button,但遇到了一個問題,已free的button,的name仍會存在,系統無法產生同name的button,請問free後之元件,是仍然存在記憶體中嗎?後來我用destory也是同樣的情況?請問該如何處理? 謝謝你!
------
將問題盡快結案也是一種禮貌! |
mitchellhu
一般會員 發表:23 回覆:53 積分:15 註冊:2007-06-12 發送簡訊給我 |
danny版主及各位回復我的各位大老,真的很感謝您們。
基本上我是新手,所以對於問題的描述真的能力不足。我初始想像動態產生Button這件事是不會太困難的,但當我真實實作時卻遇到不少問題。我覺得有必要把我的真正問題講清楚一下。
嗯故事是這樣的:
我的需求是有2個panel(panel1,panel2),在panel1是作為各項功能button的container. panel上的button是動態產生的(主要的原因buttn的數量會因為使用者需求而改變),button的caption也是動態定義的。而panel2上的button 也是根據panel1上的button動態的對應ColorButton. Colorbun.caption也是對應panel1.button.caption。
本來我的認知是cpation值的取得和傳遞是主要的問題,所以才提出了本項問題。哈哈,結果連剛開始的動態產生panel1就過不了關了。真是有愧於各位的回復。
目前我程式已可在panel上動態生成5個button了。code如下:
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, ColorButton ; type
TForm1 = class(TForm)
Button1: TButton;
Panel1: TPanel;
Edit1: TEdit;
Panel2: TPanel;
ColorButton1: TColorButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject);
var
ButtonArray:array[0..4] of TButton;
ColorBtnArray:array[0..4] of TColorButton;
CaptionArray:array[0..4] of String;
i,j:integer; begin //訂義新增panel1 上新增button的caption
CaptionArray[0] := '作業一';
CaptionArray[1] := '作業二';
CaptionArray[2] := '作業三';
CaptionArray[3] := '作業四';
CaptionArray[4] := '作業五'; for i := 0 to 4 do
begin
//產生panel1的button
ButtonArray[i] := TButton.Create(Self);
j := Round(((panel1.Width -20)-(75*5))/4);
Edit1.Text := IntToStr(ButtonArray[i].Width);
ButtonArray[i].Name := 'fmPan1Btn' IntToStr(i);
ButtonArray[i].Caption := CaptionArray[i];
ButtonArray[i].Visible := true;
ButtonArray[i].Top:= Round(panel1.Height *0.5) -
Round(ButtonArray[i].Height * 0.5);
ButtonArray[i].Left := 10 ((ButtonArray[i].Width j) * i);
ButtonArray[i].parent := panel1; //產生panle2的ColorButon
ColorBtnArray[i] := TColorButton; end; end; 所以我的問題就比較單純了:當使用者已按下Button1在panel1上產生5個button後,使用再按Button1就會產生問題,因為重複產生了。我試過在產生pnael上的button前,先檢查是否有button存在,若有則button.free。但無論是free或destory後,再按Butoon時仍有原有button.name重複問題。請問應如何解決? PS:danny版主,我之會想學習自已處理原件,係拜讀您的大作Delphi 元件設計初步(一)後,才開始產生的。您所寫出的文件真的可以引領delphi初學者,真的很感激您。
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |