TStringListの使い方について

解決


グロッキー  2005-06-23 00:54:53  No: 15858

コンポーネント作っています。
要するに、Property に TstringList を使いたいのですが
どうすればよいのでしょうか?
ソースは大体(一部削除)以下のようになっているのですが・・・

------
TUser = class(TCustomComboBox)
private
  fDefaultList: TStringList;
  fUserList: TStringList;
public
  procedure SetDefaultList(Value: TStringList);
  procedure SetUserList(Value: TStringList);
  property  DefaultList: TStringList read FDefaultList write SetDefaultList;
  property  UserList: TStringList read FUserList write SetUserList;
------
procedure   TUser.SetDefaultList(Value: TStringList);
begin
  FDefaultList.Assign(Value);
  Process;
end;

procedure TUser.SetUSerList(Value: TStringList);
begin
  FUserList.Assign(Value);
  Process;
end;

procedure TUser.Process;
begin
  Self.Items.Clear;
  Self.Items.Add(FDefaultList.Text);
  Self.Items.Add(FUserList.Text);
end;
------


ん?  2005-06-23 02:06:41  No: 15859

> どうすればよいのでしょうか?
申し訳ありませんが、聞きたいことがわかりません。
「書き方がこれでいいか?」ということであれば、
『別に間違ってないと思います』と回答しておきます。


グロッキー  2005-06-23 02:22:09  No: 15860

すみません。

メイン側でボタンを押したときに以下の処理してます。
User1.DefaultList.Add('A');
User1.DefaultList.Add('B');
User1.DefaultList.Add('C');

その後、DropDownListの中に'A','B','C'が表示されればいいのですが
空のままでなにも登録されないんです。
procedure TUser.Process;が動作していないんじゃないかと
思われるのですが、どうすれば動作するのかを教えてください。


グロッキー  2005-06-23 02:26:09  No: 15861

ひょっとすると・・・

DefaultListおよび、UserList って
もしかすると、項目の変更(追加や削除)しても
SetDefaultList や SetUserList は呼ばれないのでしょうか?

だとすれば、項目が変更されたときに process が呼ばれるように
したいのですが、どうすればよいのでしょうか?


ん?  2005-06-23 02:38:03  No: 15862

なるほど、わかりました。

> DefaultListおよび、UserList って
> もしかすると、項目の変更(追加や削除)しても
> SetDefaultList や SetUserList は呼ばれないのでしょうか?
正解です。

SetDefaultList や SetUserList が呼ばれるには、

DefaultList := どこかのStringList

のように、インスタンス自身を代入しようとした場合に発生します。

では、どうするかというと、TStringListには、内容の変化を知るOnChangeイベントがあります。

TUserクラスに、TNotifyEvent と同じ型のメソッド・・・
例えば以下のようなものを作成します。
procedure OnStringListChange(Sender: TObject);
begin
  Process;
end;

あとは、イベントを割り当てておけばよし。
fDefaultList  := TStringList.Create;
fDefaultList.OnChange := OnStringListChange;

これで、Process メソッドが発生するようになります。


グロッキー  2005-06-23 02:46:42  No: 15863

ありがとうございました。

(ずっと)さきほどから、試行錯誤して、
今、同じ方法にたどり着きました。
自己レス解決と思ったのですが・・・

すでに回答されてしまったようです。
もっと早く気づけば迷惑かけなかったと自己嫌悪してます。

OnChangeが発生したときに処理するってことは、
SetDefaultListとSetUSerListは不要でいいのかな?
試しにやってみようと思います。

お手数をおかけしました。


グロッキー  2005-06-23 02:47:19  No: 15864

チェック付け忘れました。


ん?  2005-06-23 03:16:31  No: 15865

> OnChangeが発生したときに処理するってことは、
> SetDefaultListとSetUSerListは不要でいいのかな?

残しておいたほうがいいでしょう。

  property  UserList: TStringList read FUserList write FUserList;

にしてしまったとき、

User1.UserList := どっかのTStringList;

と書いてしまうと、元々User1 で確保していたインスタンスへの参照が失われてしまいます(いわゆるメモリーリークの発生)。
その後、どっかのTStringList.Free と先に破棄した後で、User1.UserListに対してAdd等しようとすると、アクセス違反が発生します。

SetUSerListを使わなくするなら、読み取り専用プロパティとしたほうがいいでしょう。
property  UserList: TStringList read FUserList;

読み取り専用と言っても FUserListの参照するアドレスが外部から変更できないだけで、FUserListの内容は変更できます。


グロッキー  2005-06-23 04:14:42  No: 15866

ちなみにやってみました。

おっしゃるとおり?かどうかわからないんですが・・・
エラーが発生します。
生半可なエラーじゃなくて・・・
メッセージはOKボタンを押しても無限表示になるし
デバッグの終了はできないどころか
Delphi自体も終了できないようになってしまいました。

お世話になりました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加