TRichEditに高速で追加していくには?

解決


やまちゃん  2002-11-12 23:48:14  No: 2097

TRichEditに文字列(可変長)を追加していくには、
どの方法が高速に行えるのでしょうか?
1万行くらいになってくるとだんだん遅くなってくるのは、しょうがない事なのですが、できるだけ遅くならない方法を探しています。
文字列中にはCRLFがある場合とない場合があります。

TRichEdit1.Add(文字列)
TRichEdit1.SelText := 文字列
TRichEdit1.Text := TRichEdit1.Text + 文字列

初歩的な質問ですいません。他にやり方があるなら教えていただけないでしょうか
よろしくお願いします。


にしの  2002-11-13 00:30:34  No: 2098

処理されている内容を逐一表示する必要はありますか?
なければ、
RichEdit1.Lines.BeginUpdate;
と、
RichEdit1.Lines.EndUpdate;
でくくれば早くなると思います。


やまちゃん  2002-11-13 00:43:50  No: 2099

にしの様、ありがとうございます。
>処理されている内容を逐一表示する必要はありますか?
必要あります。
HideSelectionをfalseに設定して
追加された文字列を確認したいのです。

何かよい方法はありますか?


にしの  2002-11-13 00:56:21  No: 2100

> >処理されている内容を逐一表示する必要はありますか?
> 必要あります。
たぶん誤解されていると思います。
たとえば、
ABC
を足し、
DEF
を足し、
GHI
を足したいというときに、

処理的には、
ABCDEFGHI
を足したことと同じですが、それを、
ABC
を足して表示し直し、
DEF
を足して表示し直し、
GHI
を足して表示し直すと、時間がかかります。
この表示も必要かということです。
通常は、猛スピードで追加されていく文字列が描画されるだけです。
# 実際は、追加するだけではスクロールしないので、スクロールバーが小さくなるだけ
秒がしなければ、処理を終えた後に結果が表示されます。

たとえば、

for i:=1 to 1000 do
begin
  RichEdit1.Lines.Add('ABCDEFGHIJKLMNOP');
end;

とする場合と、
RichEdit1.Lines.BeginUpdate;
for i := 1 to 1000 do
begin
  RichEdit1.Lines.Add('ABCDEFGHIJKLMNOP');
end;
RichEdit1.Lines.EndUpdate;

とした場合、BeginUpdate,EndUpdateを使用した方が処理結果は早いです。
# 環境によりますが、前者が1683msec, 後者が1552msecでした

どうしても表示させたいのであれば、高速にすることは無理と思います。
他の処理の中で高速化するしかありません。


Taku  2002-11-13 17:07:47  No: 2101

追加する文字を表示しながら処理を行うのは
高速化の逆に、遅らす必要が出てくると思うのですが?

参考までに
RichEditに直接追加せずにTStringListを作り、Listに追加
最後にRichEditに代入する事で、数倍高速化することが出来ると思います
(もちろん途中の表示はできませんが)


にしの  2002-11-13 18:25:30  No: 2102

直接追加するだけなら、TStringListを使った方が早いですね。
でもSelTextを使うようですので、そうなるとSelStartなども使うでしょうから、今から変更するよりは、BeginUpdateを使った方が作業効率が良いと思います。

単純に、最初(最後)に追加するためにSelTextならば、言い換えれば、
「文字列の挿入箇所が、キャレット位置に依存せずに計算で簡単に出せる」
のであれば、TStringListを使った方がいいです。


やまちゃん  2002-11-13 18:44:37  No: 2103

>どうしても表示させたいのであれば、高速にすることは無理と思います。
どうしても表示させたいのです。

質問が悪かったのかもしれません。高速化したいのではなく、
1000行、2000行と追加していっても、できるだけ速度の落ちない方法を教えていただきたいのです。

例えば
for i := 1 to 1000 do begin
  RichEdit1.Text := RichEdit1.Text + 'ABCDEFGHIJKLMNOP';
  RichEdit1.Refresh; //画面に表示するため
end;
これなんかは、追加していくたびに遅くなっていきます。
今現在では、
RichEdit1.SelStart := Length(RichEdit1.Text)
RichEdit1.SelText := 'ABCDEFGHIJKLMNOP';
を使用して追加していっています。
追加していっても、さほど遅くなっていないのですが、もしこの方法よりも遅くならない方法があるなら教えてほしいという質問だったのです。

にしの様、Taku様、お返事遅くなり申し訳ありませんでした。


hatena  2002-11-13 19:17:49  No: 2104

>今現在では、
>RichEdit1.SelStart := Length(RichEdit1.Text)
>RichEdit1.SelText := 'ABCDEFGHIJKLMNOP';
>を使用して追加していっています。
>追加していっても、さほど遅くなっていないのですが、もしこの方法よりも遅くならない方法があるなら教えてほしいという質問だったのです。

RichEditの能力の限界ですね。RichEditはWindowsのDLLで提供されている
コントロールのラッパーですので、その能力以上を出すことはできませ
ん。

表示だけなら、TListBox を使うか、編集もしたいなら、エディタを自作
するか、TEditor とか SonEditor とかの高性能なVCLコンポーネントを
利用するかですね。


hatena  2002-11-13 19:22:29  No: 2105

訂正です。m(_ _)m
SonEditor(誤)→TSonEdit(正)


やまちゃん  2002-11-13 21:37:18  No: 2106

hatena様、ありがとうございます。
>表示だけなら、TListBox を使うか、編集もしたいなら、エディタを自作
>するか、TEditor とか SonEditor とかの高性能なVCLコンポーネントを
>利用するかですね。
表示するだけです。編集はまったく行いません。(ReadOnlyです)

なのでTListBoxを使いたいと思ったのですが、RichEditのHideSelectionのように常に最新の文字列を表示させたいのですが、その方法がわかりません。
このようなことは、可能なのでしょうか、自分で作るしかないのでしょうか。


やまちゃん  2002-11-13 22:50:47  No: 2107

ListBoxのItemIndexを設定すればできることがわかりました。
ListBox1.ItemIndex := Length(ListBox1.Count);

あとは、CRLFがある場合(文字列中のどこにあるか決まっていない)の処理について
が残っているため(さほど難しくないと思いますが)、質問等があるかもしれないのでとりあえず解決マークをつけないでおきます。

その時はよろしくお願いします。
問題なく動くようであれば、ご報告にあがります。


やまちゃん  2002-11-14 01:11:18  No: 2108

TListBoxのAddItemは一行に入力できる文字数が限られているのですか?
それとも、メモリなどの使用状況により制限が変わるのですか?
自分の環境で試してみたところ32766文字までは表示できたのですが、
それ以上はエラーになってしまいます。
PCが一台しかないために、確認できません。わかる方や試していただける方がいたらよろしくお願いします。
var
 i:Integer;
 str:String;
begin
  for i := 1 to 32766 do
    str := str + 'A';
  ListBox1.AddItem(str,nil);
end;


にしの  2002-11-14 02:05:14  No: 2109

OSによっては、32KBの制限がありますよ。


やまちゃん  2002-11-14 03:36:53  No: 2110

にしの様、ありがとうございます。

TMemoでの32KB制限があったのは知っていたのですが、
TListBoxでもあるとは思いませんでした。

TListBoxで無事に出来そうです。表示することが、ここまで変わるのかということがよくわかりました。
にしの様、Taku様、hatena様、ありがとうございました。


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








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