下記の質問で解決したかに見えたのですが,よく見ると困ったことが
おきていました。
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 です。
> Font色を変えるまでは,そういう症状はありませんでした。
> どうしたらいいのでしょうか。
再現するコードがないとわかりません。
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 です。
> コードは,全部で600行を超えていますので,
えと、実際のコードはどうでもよいのです。
ある不可解な現象があるとき、それを再現する最小のコードがあればその原因が
わかります。といっても、逆に言えば、原因の見当がつかないと再現する最小の
コードも書けないわけですが。
> Font色を変えるまでは,そういう症状はありませんでした。
であれば、Wait の Application.ProcessMessages; をコメントアウトして
試してみてください。
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;
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に正しい表示がなされます。
taに来た時、Wait中なので、MouseMoveが発生していないと思います。
Halbow です。
> この変化の後,Edit.Textに正しい表示がなされます。
なにが「不具合」なのかわかりません。「さ」を通過したんでは?
> taに来た時、Wait中なので、MouseMoveが発生していないと思います。
そうですね。結局、Sleep() をしている間にユーザがマウスを動かすことが
「不具合」の原因だと思います。Sleep() ではなく Timer を使うべきかも
しれませんね。ユーザがものすごい勢いでマウスを移動させたとき、
シークエンシャルに色を変更するロジックと不整合を起こすのだと思います。
これはタイマを使っても同じような気がします。
?さん,Halbowさん,レスありがとうございます。
>なにが「不具合」なのかわかりません
説明が足りなくて,申し訳ありません。Delphiを使うのも
本格的にソフトを作るのも初めてなので,いろいろと迷惑を
かけます。また,エクセルのVBAを独学しただけなので,説明もうまく
できません。
これは,まだローマ字を知らない小学校3年生以下の子どもに,ローマ字
で文章を入力してもらうためのソフトで,「か」をマウスで選んだら,
Edit1に「か」,Edit2に「ka」,Edit3に「KA」を表示させ,キーボード
のボタン配置をPanelで28個(「,」「。」も含む)並べてあります。
平仮名を選ぶための表を,StringGridで11列17行のセルに表示しています。
ですから,「か」から「た」へ移動するときは,「さ」のセルを通ってし
まいます。
上の動きだけだったら,何も不具合なく出来ていたんですが,「しゃ」
の場合「s」「y」「a」という順番を分からせるため,順に色を変えて
表示できたら分かりやすいと思い,取り組んだところです。
このあと色の変化を一回だけでなく,マウスが動くまでループさせる
ところまでいけたら,完成です。
うまく説明できたか不安ですが,よろしくお願いします。
Halbow です。
> 順に色を変えて
> 表示できたら分かりやすいと思い,取り組んだところです。
Sleep(400) を三回実行するルーチンは、実行するのに最低1.2秒かかります。
一方、StringGrid 上でマウスを動かすと、1秒間に10以上のセルを通過
させることもできるでしょう。このとき、どのような動作をすることがお望み
なんでしょうか?
見る限りでは、
・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを起動。
・スレッドが終了したら、同じかな文字が選択されていれば、またスレッドを起動。
だけですむと思います。
スレッドでは、
・指定した文字のパネルを順に点滅
・点滅が終えたら終わったことをメインスレッドに知らせる
とします。
ただしこの場合、問題が出てきます。
「か」(さ)「た」と移動した場合、K,A,S,A,T,Aと点滅しますが、素早く移動させれば、スレッドは別々に点滅させていきますので、大げさに言えば、
K,S,T,A,A,A
と点滅することも考えられます。
これを解決するために、別のかな文字に移動したら、現在動いているスレッドを破棄させます。
・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを起動。
これを、
・ある1つのかな文字にマウスが肺ったら、既に起動しているスレッドを終了させ、新規に、パネルを点滅させるスレッドを起動。
とします。
これで、「か」(さ)「た」と移動した場合(「か」にちょっといて、「さ」を通過し「た」に移動した場合)、
K,A,S,T,A
と点滅します。
# Sは、移動中に「さ」を通過するときに色が変わってしまいます。
Halbowさん、にしのさん、こんにちは。
>このとき、どのような動作をすること
これは,にしのさんのレスにある通りで
>これを解決するために、別のかな文字に移動したら、現在動いているスレッ>ドを破棄させます。
>・ある1つのかな文字にマウスが入ったら、パネルを点滅させるスレッドを>起動。
>これを、
>・ある1つのかな文字にマウスが肺ったら、既に起動しているスレッドを終>了させ、新規に、パネルを点滅させるスレッドを起動。
>とします。
まさに,この動きです。
でも,力不足の限りでそのスレッド(procedureのことかな?)をどこに,
どのように書くのかがさっぱりわからないのです。
スレッドによるサンプルです。
「あかさたな」しかありませんが^^;
http://www.overs.jp/software/tips/kanatest.lzh
色を変える部分だけ参考にしてください。
11列17行であれば、2次元の位置を、一次元に変更し、文字列の配列を持たせた方が簡単かと思います。
# 全てcaseに書くと大変です
ここでいうスレッドとは、TThreadのオブジェクトの事です。
アプリケーションは、1つのプロセス上で動きます。この1つのプロセス上に、1つ以上のスレッドが動作しています。
OSの中で、複数のアプリケーションが動いている(複数のプロセスが動いている)のと似たようなものです。
スレッドは複数いくつでも(Borlandの推奨は16スレッドまでのようです)動作させることが出来ますが、CPUが1つであれば、CPUの能力を分割することになるので、増える分だけ負荷も大きくなり、速度にも影響が出てきます。
詳しくは、ヘルプでTThreadを調べてみてください。
にしのさん、スレッドのサンプルありがとうございます。
初めてのものばかりで、ほとんど理解できませんが、動きは
よく分かりました。
このようなスレッドを書く場合,「新規作成」「その他」
「スレッドオブジェクト」と選んでいくのでしょうか。選んだとき
クラス名を書くダイアログが出ましたが,クラス名には何を書いたら
いいのでしょうか。
あと1つ。サンプルですが,マウスでいろいろ動かすと終了できなく
なりました。やりかたがまずかったのでしょうか。
こっちの環境は,今は職場でWinXP,Delphi6 Personal です。
Form1のOnDestroyイベントで、
if Assigned(Thread) then Therad.Terminate;
をしてみてください。
それくらいしか思いつきません^^;
スレッドの作成はそれであっています。
クラス名は適当でOKです。
Delphiは、慣用的にクラス名をTから始めることになっています。
サンプルの終了の件ですが,1文字のみの色の変化をさせた後は
終了できました。2文字目に移ると,固まって応答しなくなり再起動
することしかできませんでした。
スレッドって難しいんですね。でも,せっかくのコードですので
時間をかけて応用したいと思います。また,スレッドの作成にも
挑戦してみます。
解決したわけではありませんが,もう少し参考書等で勉強をして
から,また考えます。
なにか気付いたことがありましたら,またお願いします。
Halbowさん,にしのさん,本当に有難うございました。
ツイート | ![]() |