Waitで困った症状を回避するには?


なんとん  2004-01-07 06:24:56  No: 6553

下記の質問で解決したかに見えたのですが,よく見ると困ったことが
おきていました。

https://www.petitmonte.com/bbs/answers?question_id=1283

procedure TForm1.StringGrid1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  RC, CC: integer;

  procedure IroHenko2(P1, P2: integer);
    procedure Wait(duration:DWORD);
    begin
      Application.ProcessMessages;
      Sleep(duration)
    end;

  begin
     Panels[P1].Color := clYellow;
     Panels[P2].Color := clYellow;
       Wait(400);
       Panels[P1].Font.Color := clRed;
       Wait(400);
       Panels[P2].Font.Color := clRed;
       Wait(400);
       Panels[P1].Font.Color := clBlack;
       Panels[P2].Font.Color := clBlack;
  end;

これで,Font色は時間をおいて変化しますが,Edit2とEdit3のTextが
カーソルのあるセルのものとは,違うものになります。
例えば,「か」から「た」へカーソルを移動させると,Edit2のTextは
「ta」からしばらくするとカーソルが通ってきた「sa」に変わります。
Font色を変えるまでは,そういう症状はありませんでした。
どうしたらいいのでしょうか。


Halbow  URL  2004-01-07 06:31:13  No: 6554

Halbow です。

> Font色を変えるまでは,そういう症状はありませんでした。
> どうしたらいいのでしょうか。

再現するコードがないとわかりません。


なんとん  2004-01-07 07:18:00  No: 6555

Halbowさん,またお世話になります。
コードは,全部で600行を超えていますので,上の続きを
少し載せておきます。この後は,二つのCase文の繰返しです。

begin
  StringGrid1.MouseToCell(x, y, RC, CC);
  if (RC = -1) or (CC = -1) then Exit;
  if (Kx <> RC) or (ky <> CC) then  
  begin
  kisoshori;
  Edit1.Text := StringGrid1.Cells[RC, CC];
  Kx := RC; Ky := CC;           
  Case Kx of
    10: begin
      Case Ky of
        0..4: begin
         IroHenko1(RC10[CC].PnlNo1);
         Edit2.Text := RC10[CC].komoji;
         Edit3.Text := RC10[CC].oomoji;
        end;
        6..10,12..16: begin
         Edit2.Text := RC10[CC].komoji;
         Edit3.Text := RC10[CC].oomoji;
         IroHenko3(RC10[CC].PnlNo1,RC10[CC].PnlNo2,RC10[CC].PnlNo3);
        end;
         5,11: kisoshori;
        end;
      end;
    9: begin
      case Ky of
        0..4, 6..10: begin
         Edit2.Text := RC9[CC].komoji;
         Edit3.Text := RC9[CC].oomoji;
         Edit4.Text := RC9[CC].komoji2;
         Edit5.Text := RC9[CC].oomoji2;
         IroHenko2(RC9[CC].PnlNo1, RC9[CC].PnlNo2);
        end;

>Font色を変えるまでは,そういう症状はありませんでした。
それまでは,カーソルが「た」の上にある間は,Edit2のTextは「ta」の
ままだったのです。ちなみにEdit3は大文字の「TA」です。


Halbow  URL  2004-01-07 10:28:03  No: 6556

Halbow です。

> コードは,全部で600行を超えていますので,

えと、実際のコードはどうでもよいのです。
ある不可解な現象があるとき、それを再現する最小のコードがあればその原因が
わかります。といっても、逆に言えば、原因の見当がつかないと再現する最小の
コードも書けないわけですが。

> Font色を変えるまでは,そういう症状はありませんでした。

であれば、Wait の Application.ProcessMessages; をコメントアウトして
試してみてください。


Halbow  URL  2004-01-07 11:21:39  No: 6557

Halbow です。

Application.PrecessMessages をやめて、以下のようにしてみてください。

procedure IroHenko2(P1, P2: integer);
  procedure Wait(duration:DWORD);
  begin
    Panels[P1].Refresh;
    Panels[P2].Refresh;
    Sleep(duration)
  end;
begin
  Panels[P1].Color := clYellow;
  Panels[P2].Color := clYellow;
  Wait(400);
  Panels[P1].Font.Color := clRed;
  Wait(400);
  Panels[P2].Font.Color := clRed;
  Wait(400);
  Panels[P1].Font.Color := clBlack;
  Panels[P2].Font.Color := clBlack;
end;


なんとん  2004-01-07 15:57:09  No: 6558

Halbowさん,夜遅くまで考えていただき有難うございます。

>Application.ProcessMessages; をコメントアウト
すると,今までのようにFont色は変わらずWaitの時間後
Panels.ColorやEdit.Textが変わります。

さて,
> Panels[P1].Refresh; Panels[P2].Refresh;
に置き換えると,「か」から「た」へカーソルを移動させた場合
Edit.Textに「sa」が表示されることは,なくなりました。ところが
今度は,Panels.Colorに不具合がでます。「か」から「た」へ移動する
と,Panelの「K」「A」「S」「T」のPanels.Colorが黄色になり,
Panels.Font.Colorは,「S」「A」「T」「A」の順に赤に変わります。
この変化の後,Edit.Textに正しい表示がなされます。


  2004-01-07 17:35:13  No: 6559

taに来た時、Wait中なので、MouseMoveが発生していないと思います。


Halbow  URL  2004-01-07 18:52:30  No: 6560

Halbow です。

> この変化の後,Edit.Textに正しい表示がなされます。

なにが「不具合」なのかわかりません。「さ」を通過したんでは?

> taに来た時、Wait中なので、MouseMoveが発生していないと思います。

そうですね。結局、Sleep() をしている間にユーザがマウスを動かすことが
「不具合」の原因だと思います。Sleep() ではなく Timer を使うべきかも
しれませんね。ユーザがものすごい勢いでマウスを移動させたとき、
シークエンシャルに色を変更するロジックと不整合を起こすのだと思います。
これはタイマを使っても同じような気がします。


なんとん  2004-01-07 21:01:08  No: 6561

?さん,Halbowさん,レスありがとうございます。

>なにが「不具合」なのかわかりません
説明が足りなくて,申し訳ありません。Delphiを使うのも
本格的にソフトを作るのも初めてなので,いろいろと迷惑を
かけます。また,エクセルのVBAを独学しただけなので,説明もうまく
できません。

これは,まだローマ字を知らない小学校3年生以下の子どもに,ローマ字
で文章を入力してもらうためのソフトで,「か」をマウスで選んだら,
Edit1に「か」,Edit2に「ka」,Edit3に「KA」を表示させ,キーボード
のボタン配置をPanelで28個(「,」「。」も含む)並べてあります。
平仮名を選ぶための表を,StringGridで11列17行のセルに表示しています。
ですから,「か」から「た」へ移動するときは,「さ」のセルを通ってし
まいます。
  上の動きだけだったら,何も不具合なく出来ていたんですが,「しゃ」
の場合「s」「y」「a」という順番を分からせるため,順に色を変えて
表示できたら分かりやすいと思い,取り組んだところです。
  このあと色の変化を一回だけでなく,マウスが動くまでループさせる
ところまでいけたら,完成です。

うまく説明できたか不安ですが,よろしくお願いします。


Halbow  2004-01-07 21:56:36  No: 6562

Halbow です。

> 順に色を変えて
> 表示できたら分かりやすいと思い,取り組んだところです。

Sleep(400) を三回実行するルーチンは、実行するのに最低1.2秒かかります。
一方、StringGrid 上でマウスを動かすと、1秒間に10以上のセルを通過
させることもできるでしょう。このとき、どのような動作をすることがお望み
なんでしょうか?


にしの  2004-01-07 22:21:55  No: 6563

見る限りでは、
・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを起動。
・スレッドが終了したら、同じかな文字が選択されていれば、またスレッドを起動。
だけですむと思います。
スレッドでは、
・指定した文字のパネルを順に点滅
・点滅が終えたら終わったことをメインスレッドに知らせる
とします。

ただしこの場合、問題が出てきます。
「か」(さ)「た」と移動した場合、K,A,S,A,T,Aと点滅しますが、素早く移動させれば、スレッドは別々に点滅させていきますので、大げさに言えば、
K,S,T,A,A,A
と点滅することも考えられます。

これを解決するために、別のかな文字に移動したら、現在動いているスレッドを破棄させます。
・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを起動。
これを、
・ある1つのかな文字にマウスが肺ったら、既に起動しているスレッドを終了させ、新規に、パネルを点滅させるスレッドを起動。
とします。
これで、「か」(さ)「た」と移動した場合(「か」にちょっといて、「さ」を通過し「た」に移動した場合)、
K,A,S,T,A
と点滅します。
# Sは、移動中に「さ」を通過するときに色が変わってしまいます。


なん  2004-01-07 22:49:08  No: 6564

Halbowさん、にしのさん、こんにちは。

>このとき、どのような動作をすること

これは,にしのさんのレスにある通りで

>これを解決するために、別のかな文字に移動したら、現在動いているスレッ>ドを破棄させます。
>・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを>起動。
>これを、
>・ある1つのかな文字にマウスが肺ったら、既に起動しているスレッドを終>了させ、新規に、パネルを点滅させるスレッドを起動。
>とします。

まさに,この動きです。
  でも,力不足の限りでそのスレッド(procedureのことかな?)をどこに,
どのように書くのかがさっぱりわからないのです。


にしの  2004-01-07 23:06:01  No: 6565

スレッドによるサンプルです。
「あかさたな」しかありませんが^^;
http://www.overs.jp/software/tips/kanatest.lzh

色を変える部分だけ参考にしてください。
11列17行であれば、2次元の位置を、一次元に変更し、文字列の配列を持たせた方が簡単かと思います。
# 全てcaseに書くと大変です


にしの  2004-01-07 23:10:25  No: 6566

ここでいうスレッドとは、TThreadのオブジェクトの事です。
アプリケーションは、1つのプロセス上で動きます。この1つのプロセス上に、1つ以上のスレッドが動作しています。
OSの中で、複数のアプリケーションが動いている(複数のプロセスが動いている)のと似たようなものです。
スレッドは複数いくつでも(Borlandの推奨は16スレッドまでのようです)動作させることが出来ますが、CPUが1つであれば、CPUの能力を分割することになるので、増える分だけ負荷も大きくなり、速度にも影響が出てきます。
詳しくは、ヘルプでTThreadを調べてみてください。


なんとん  2004-01-08 00:30:34  No: 6567

にしのさん、スレッドのサンプルありがとうございます。

初めてのものばかりで、ほとんど理解できませんが、動きは
よく分かりました。

  このようなスレッドを書く場合,「新規作成」「その他」
「スレッドオブジェクト」と選んでいくのでしょうか。選んだとき
クラス名を書くダイアログが出ましたが,クラス名には何を書いたら
いいのでしょうか。

  あと1つ。サンプルですが,マウスでいろいろ動かすと終了できなく
なりました。やりかたがまずかったのでしょうか。
こっちの環境は,今は職場でWinXP,Delphi6 Personal です。


にしの  2004-01-08 00:48:10  No: 6568

Form1のOnDestroyイベントで、
if Assigned(Thread) then Therad.Terminate;
をしてみてください。
それくらいしか思いつきません^^;

スレッドの作成はそれであっています。
クラス名は適当でOKです。
Delphiは、慣用的にクラス名をTから始めることになっています。


なんとん  2004-01-08 03:43:24  No: 6569

サンプルの終了の件ですが,1文字のみの色の変化をさせた後は
終了できました。2文字目に移ると,固まって応答しなくなり再起動
することしかできませんでした。

  スレッドって難しいんですね。でも,せっかくのコードですので
時間をかけて応用したいと思います。また,スレッドの作成にも
挑戦してみます。

  解決したわけではありませんが,もう少し参考書等で勉強をして
から,また考えます。
  なにか気付いたことがありましたら,またお願いします。

Halbowさん,にしのさん,本当に有難うございました。


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

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






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