喫茶XRAYトップページ

[▲前のスレッド]

[7376] Form1.Components[]の使い方返信 削除
2014/3/18 (火) 13:19:17 taki
フォームにComboBoxをたくさん並べていたのですが、
画面がきたないと言われてしまいました。(T_T)

そこで、今度はLabelを並べてLabelをクリックしたら、
ComboBoxを開き、ドロップダウンリストからデータを選択し、
選択した文字列をLabelに表示するという形にしました。

教えてもらいたいことは、エラー処理の方法です。
プログラムはとりあえず動くのですが、Form1.Components[]
命令の使い方に自信がありません。

また、TLabel(コンポーネント).Caption := とか書いていますが、
コンポーネントを予めチェックした方がいいんでしょうね。たぶん。

Form1上にLabelを3個、ComboBoxを1個配置しています。
以下にソースです。

(定義部は省略)

var
  AComponentIndex : integer;  // Form1の各Labelの番号を記憶

implementation

{$R *.dfm}

// ComboBoxの選択した値をLabelに代入
procedure TForm1.ComboBox1Click(Sender: TObject);
begin
  TLabel(Form1.Components[AComponentIndex]).Caption :=
         ComboBox1.Items.Strings[ComboBox1.ItemIndex];
  ComboBox1.Hide;   // 消す
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Hide;
  Label1.Caption := '魚';  // 書き換え対象
  Label2.Caption := '花';
  Label3.Caption := '木';
end;

procedure TForm1.SetDataComboBox;
begin
  case AComponentIndex of
    0 : ComboBox1.Items.CommaText := 'タイ,マグロ,シャケ';
    1 : ComboBox1.Items.CommaText := 'たんぽぽ,すみれ,パンジー';
    2 : ComboBox1.Items.CommaText := 'サクラ,ウメ,マツ';
  end;
end;

// label1,label2,label3で共有するイベント
procedure TForm1.Label1Click(Sender: TObject);
begin
  // クリックしたLabelのComponentIndexを記憶
  AComponentIndex := TLabel(Sender).ComponentIndex;
  ComboBox1.Text := 'クリックしてください';
  // ComboBoxにデータをセット
  SetDataComboBox;
  // ComboBoxをLabelの位置に合わせる
  ComboBox1.Top := TLabel(Sender).Top + TLabel(Sender).Height;
  ComboBox1.Left := TLabel(Sender).Left;
  ComboBox1.Show;
  // 自動で開く
  ComboBox1.Perform(CB_SHOWDROPDOWN, 1, 0);
end;


[7377] Re:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 14:45:01 taki
> また、TLabel(コンポーネント).Caption := とか書いていますが、
> コンポーネントを予めチェックした方がいいんでしょうね。たぶん。
>
> Form1上にLabelを3個、ComboBoxを1個配置しています。


先ほどのForm1にListBox1個、Button1個を追加で配置します。
ボタンをクリックするとコンポーネントの一覧が得られます。

procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to Form1.ComponentCount - 1 do begin
    ListBox1.Items.Append(inttostr(i) + ' ' + Form1.Components[i].Name);
  end;
end;

これでComponentIndexとLabelを確認しないといけないのが面倒です。
うっかりLabelを削除したりしたらアウトですね。



[7378] Re2:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 17:12:58 snail
▼ takiさん

>教えてもらいたいことは、エラー処理の方法です。
>プログラムはとりあえず動くのですが、Form1.Components[]
>命令の使い方に自信がありません。


いつも教えていただいているので、私で解る範囲で
お答えしたいのですが。「何が知りたいのか」わかりません。

とりあえず

  if Form1.Components[AComponentIndex] is TLabel
  begin
    if 0 <= ComboBox1.ItemIndex then
      TLabel(Form1.Components[AComponentIndex]).Caption :=
          ComboBox1.Items.Strings[ComboBox1.ItemIndex];
  end;

エラーチェックを追加してみました。
※ 頭上デバッグなのでコンパイルエラーが発生するかもしれません。



[7379] Re3:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 19:28:35 taki
▼ snailさん
 
早速の回答ありがとうございます。

> 私で解る範囲で
> お答えしたいのですが。「何が知りたいのか」わかりません。


今回初めてForm1.Components[]を使ったプログラムを書きました。

Labelの情報はSenderを介してComboBoxに得ることができるのですが、
ComboBoxのイベント手続きでComboBoxの選択した結果をどうやって
元のLabelに渡したらいいのかがわからず、色々調べて
Form1.Components[]にたどり着きました。

もやもやとした「このままのコードではやばいだろうな」という
レベルの質問となってしまいました。

型は if ○ is T○ でチェックすれば良いことがわかりました。

if 0 <= ComboBox1.ItemIndex then…においては、ComboBox1の
ドロップダウンリスト以外はどこをクリックしてもComboBox1の
Clickイベントは発生しなかったので、たぶんチェックする必要は
無いように思います。
また、ドロップダウンリストの要素が無い状態でもイベントは
発生しませんでした。

クリックするLabelを変えるとComboBoxのドロップダウンリストの要素を
変える手続きSetDataComboBoxをもう少し工夫しないといけないと思います。

考えてみます。



[7381] Re4:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 20:26:13 taki
> クリックするLabelを変えるとComboBoxのドロップダウンリストの要素を
> 変える手続きSetDataComboBoxをもう少し工夫しないといけないと思います。
>
> 考えてみます。
>


度々すみません。m(_ _)m

AComponentIndexにこだわり過ぎていました。

procedure TForm1.SetDataComboBox(oya:string);
begin
  if oya = 'Label1' then ComboBox1.Items.CommaText := 'タイ,マグロ,シャケ';
  if oya = 'Label2' then ComboBox1.Items.CommaText := 'たんぽぽ,すみれ,パンジー';
  if oya = 'Label3' then ComboBox1.Items.CommaText := 'サクラ,ウメ,マツ';
end;

にして、

// label1,label2,label3で共有するイベント
procedure TForm1.Label1Click(Sender: TObject);
begin
    (省略)
  // ComboBoxにデータをセット
  SetDataComboBox(TLabel(Sender).Name);
    (省略)
end;

とすれば良いみたいです。

それと、グローバル変数AComponentIndexを使わずに、ComboBox1.Tagを変数として
使ってもプログラムは動きました。



[7384] Re5:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 21:11:54 snail
▼ takiさん

何がしたいか理解できていませんが

procedure TForm1.SetDataComboBox(oya:string);
     ↓
procedure TForm1.SetDataComboBox(oya:TObject);
begin
  if oya = Label1 then
    ComboBox1.Items.CommaText := 'タイ,マグロ,シャケ'
   else if oya = Label2 then
    ComboBox1.Items.CommaText := 'たんぽぽ,すみれ,パンジー'
   else if oya = Label3 then
    ComboBox1.Items.CommaText := 'サクラ,ウメ,マツ';
end;

と書いてもいいですよね。



[7385] Re6:Form1.Components[]の使い方返信 削除
2014/3/18 (火) 22:54:35 taki
▼ snailさん

> 何がしたいか理解できていませんが

はい。ComboBoxをそのまま使わせてもらえたらこんな苦労を
しなくて済むのに。

> procedure TForm1.SetDataComboBox(oya:TObject);

なるほど。
名前に変えなくてもObjectで比較すればいいんですね。
また、if ○ then else if ○…を使うのがベストですし。
いっぱい無駄な事をしています…。

大変勉強になります。

話は変わりますが、Labelにはhandleが無いんですね。
ComboBox1.TagにLabelのhandleを代入したら何とかできるかもと
考えたのですが砕け散りました。


[7386] Re7:Form1.Components[]の使い方返信 削除
2014/3/19 (水) 09:19:38 Mr.XRAY
う〜ん.なるほど.
コンポーネントの実行時管理は結構面倒ですね.
複数の種類の違うコントロールの連携ですね.

どんな方法がいいんでしょうね.


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82