Delphi初心者です。
Delphi7を使用しています。
以下の条件でエラーを出さずに選択された複数行を削除する方法がわかりません。
・TListView
Name:List
ViewStyle:vsReport
ReadOnly : True
MultiSelect : True
GridLines : True;
※上記以外はデフォルトの状態。
以下、プログラム中の削除関数の抜粋です。
:
:
var
i, Count, j : Integer;
tmpList : TStringList;
SelCt : Integer;
begin
// リストの行数
Count := List.Items.Count;
if(Count <> 0)then
for i := 0 to (Count-1) do
if(List.Items.Item[i].Selected)then
// 選択した行を削除する
List.Items.Delete(i);
end;
上記を実行するとエラーになります。
特に十数行以上を削除する時にエラーとなります。
これは、表示が追いつかないからなのでしょうか?
もしそうだとしたら、改善方法はあるのでしょうか?
もし、ご回答できる方がいましたら、ご指導ください。
すみません、訂正です。
宣言部の
var
i, Count, j : Integer;
tmpList : TStringList;
SelCt : Integer;
の中で、iとCount以外は不要です。
for i := 0 to (Count-1) do
を
for i := Count-1 downto 0 do
に変更してみてはいかがでしょう。
ふぐちゃん様へ
変更してみましたところ、成功しました。
本当にありがとうございます。
しかし、なぜdowntoだと上手くいくのでしょうか?
初心者で申し訳ないです。。
Countが少ない場合を考えてみるとわかりやすいと思います。
たとえばCountが5としますと、
for i := 0 to Count-1 do
は、iが0から4まで変化します。
もし、iが1のとき
List.Items.Item[i].Selected
がTrueになったとしたら、
List.Items.Delete(i);
でそのアイテムが削除され、List.Items.Countは4になります。
この状態でforループの制御変数iが4になったとき、どういうことになるでしょうか?
List.Items.Item[i].Selected
すなわち
List.Items.Item[4].Selected
は無効なアイテムを参照していることになりませんか?
1つ削除されたので、アクセス可能なアイテムは
List.Items.Item[0]
List.Items.Item[1]
List.Items.Item[2]
List.Items.Item[3]
ですから。
for i := Count-1 downto 0 do
についてはご自分で考えてみてください。
後ろから削除していけば問題ないことは、すぐに理解できると思います。
i := 0 to (Count - 1)だと、上から削除するので、仮に5行あり、その5行全てを選択していたとして、削除を実行すると、
i = 0 → 一番上を削除(この時点で残り4行)
i = 1 → 上から2番目を削除(この時点で残り3行)
i = 2 → 上から3行目を削除(もう残り2行)
i = 3 → 上から4行目を削除したいけど、もう行がない。。。。ガビィィィィーン!!!
これに対してdowntoだと、
i := (Count - 1) downto 0
i = 4 → 上から5行目(一番下)を削除(残り4行)
i = 3 → 上から4行目(一番下)を削除(残り3行)
i = 2 → 上から3行目(一番下)を削除(残り2行)
i = 1 → 上から2行目(一番下)を削除(残り1行)
i = 0 → 上から一番目(最後の一行)を削除(なくなったぞ!!!)
てな感じで、、、、分かりにくい説明ですね・・・。
書いてる途中に「ふぐちゃん」さんに書かれてました(^^;;
ふぐちゃん様、とおりすがり様、
大変勉強になりました。
なぜ、downtoだと成功するか理解できました。
本当にありがとうございました。
ツイート | ![]() |