最描写時のちらつきをなくすには?

解決


サンプー  2006-08-24 16:33:33  No: 22972  IP: [192.*.*.*]

dl6pro,xppro,Pentium Ⅳ2.6GHz です。データベースは、IBです。
画面に、panelを5個、DBNavigator、DBMemoを4個、DBTextを14個貼り付けてあります。
DBMemo1の項目(数値を文字列として格納してある)を1行毎に取得し、この項目の総数だけ、動的にLabelを作成、各LabelのCaptionに各行に対応するDBMemo2項目(文字列)を割り当てるようにするために、いかのコードを作成し、DBNavigatorOnClickイベントへ割り付けました。動作は間違いなく行なうのですが、描写に時間がかかるよう、各Labelの作成過程が目に見てわかります。どなたか、良い方法を教えてください。現在のコードは、以下の通りです。
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DBCtrls, StdCtrls, ExtCtrls, Mask;

type
  KaisuArr = Array of Integer ;
  ItemAr = Array of TLabel ;
  DayAr = Array of TMaskEdit ;
  TFrmSagyoDay = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
  
  private
    { Private 宣言 }
    SumKaiTen : Integer ; //それぞれの回数取得のため
    TenkenKai,SumKai : KaisuArr ;
    ItemLbl : ItemAr ;
    DayMaskEd : DayAr ;
    Procedure SonotaDisplay ;

  public
    { Public 宣言 }
  end;

var
  FrmSagyoDay: TFrmSagyoDay;

implementation

uses Types, DMKanri;

{$R *.dfm}


procedure TFrmSagyoDay.DBNavigator1Click(Sender: TObject;
  Button: TNavigateBtn);
begin
 SonotaDisplay;
end;

procedure TFrmSagyoDay.SonotaDisplay; //点検項目の日付とラベルの表示
  var I,s,j : Integer ;
begin
   S := DBMemo1.Lines.Count ;

   SetLength(TenkenKai,s);//配列の要素数を確定
   SetLength(SumKai,s);//配列の要素数を確定
   SumKaiTen := 0 ;
   for I := 0 to S -1 do    //配列へ格納
   begin
   TenkenKai[I] := StrToInt(DBMemo1.Lines[I]);
   SumKaiTen := TenkenKai[I] + SumKaiTen; //点検時項目実施回数の合計を計算
   SumKai[I] := SumKaiTen;
   end;
//****以上、表示用の数を算出するため****

//以下、項目表示用のラベルの動的作成
   SetLength(ItemLbl,SumKaiTen);//配列の要素数を確定
   for I := 0 to SumKaiTen-1 do
   begin
   ItemLbl[I] :=TLabel.Create(self);
     with ItemLbl[I] do
       begin
       Parent := Panel5;//Panel5に表示するため
       Visible := True ;
       Top := (15*I) +30 ;
       Left := 15;
       Tag := I;
       end;
   end;

//*******ラベルのキャプションを項目値に変換開始*****
   I := 0 ;
   j := 0 ;
while J <= S-1 do
  begin
   while  I <= SumKaiTen-1 do
   begin
    with ItemLbl[I] do
    begin
     Caption := DBMemo2.Lines[j];
     end;
    inc(I);
   end;
   inc(J) ;
   I :=SumKai[J-1];
  end;
//*******ラベルのキャプションを項目値に変換終了*****


//以下、日付入力用のMaskEditの動的作成
   SetLength(DayMaskEd,SumKaiTen);//配列の要素数を確定
   for I := 0 to SumKaiTen-1 do
   begin
   DayMaskEd[I] :=TMaskEdit.Create(self);
     with DayMaskEd[I] do
       begin
       Parent := Panel5;
       Visible := True ;
       Top := (15*I) +30 ;
       Left := 150;
       EditMask := '!9999/99/00;1;_';
       end;
   end;

  SetLength(TenkenKai,0);
  SetLength(ItemLbl,0);
  SetLength(DayMaskED,0) ;
end;

編集    削除
ん?  2006-08-24 17:27:26  No: 22973  IP: [192.*.*.*]

Labelの位置が固定なら、最初からコントロールを配置しておいて、
不要なものは Visible = False なのはだめ?

Panel5.DoubleBuffered := True;
これは・・・あまり効果なさそう。。。

他には...
Panel5の下にLabelを置いて、Caption = '準備中...'; とかにする。
1) Panel5 を非表示
2) 項目表示用のラベルの動的作成
3) Panel5 を表示
Application.ProcessMessages を適当に挟んで。

いまいちやね。

編集    削除
サンプー  2006-08-24 17:58:31  No: 22974  IP: [192.*.*.*]

ん?さん早々のレス有難うございます。

>Labelの位置が固定なら、最初からコントロールを配置しておいて、
>不要なものは Visible = False なのはだめ?
動的に作成するLabelとMaskEditの数が固定されていないので、無理だと思います。

>Panel5.DoubleBuffered := True;
>これは・・・あまり効果なさそう。。。

>他には...
>Panel5の下にLabelを置いて、Caption = '準備中...'; とかにする。
>1) Panel5 を非表示
>2) 項目表示用のラベルの動的作成
>3) Panel5 を表示

これも、試したのですが、Labelの表示、非表示時に少しストレスを感じます。
>Application.ProcessMessages を適当に挟んで。

いまいちやね。

編集    削除
サンプー  2006-08-24 18:00:23  No: 22975  IP: [192.*.*.*]

ごめんなさい。
Labelの表示、非表示時にストレスではなく、Panelの表示、非表示時にストレスを少し感じます。です

編集    削除
ん?  2006-08-24 18:40:48  No: 22976  IP: [192.*.*.*]

> 動的に作成するLabelとMaskEditの数が固定されていないので、無理だと思います。

現レコードでは10個だけど、次のレコードに移動したら5個で済んだ。
じゃ、6〜10は、非表示にしよう。
その次は、20個(も)必要だ。
でも10個しかないから、残り10個追加しよう。

・・・ということで、表示・非表示を切り換えるのは?
現在のコントロール数を管理しておく必要はあるが、生成・破棄を無駄に繰り返さないと思うのですが。

こんな意味で書いたのだけど、通じなかったかしら?
最初の質問では、レコード移動毎に、全部のコントロールを破棄・生成を行っているように感じたから。
難しい書き方でごめんね。

編集    削除
Basser  2006-08-24 18:59:16  No: 22977  IP: [192.*.*.*]

以下のようにしても駄目ですか?

procedure TFrmSagyoDay.SonotaDisplay; //点検項目の日付とラベルの表示
  var I,s,j : Integer ;
begin
  LockWindowUpdate(Handle);
  try
    
    既存処理記述部
          ↓

  finally
    LockWindowUpdate(0);
  end;
end;

編集    削除
サンプー  2006-08-24 19:55:39  No: 22978  IP: [192.*.*.*]

ん?さん、Basserさんありがとうございました。
Basserさんの方法で期待通りの結果が得られました。

編集    削除