05-15-2013, 06:39 PM,
|
|||||
|
|||||
フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
あるテキストフィールドに入力された内容にしたがって、
画面の情報を書き換えるような処理はよくあると思います。 また、画面上のボタンを押して、画面情報をサーバに送信して登録する、 という処理もよくあると思います。 このボタンが、フォーカスを受け付けない、もしくはショートカットキーが割り振られている場合に、 テキストフィールドへの入力直後にボタン押下イベントを起こすと、 ボタン押下イベントが、テキストフィールドの入力確定イベントより先に走ると思います。 ユーザは、入力した内容で更新された状態(入力確定イベント後)に、 ボタン押下イベントが走ることを期待します。 フォーカスを持たないボタンの押下時に、 先に入力確定イベントを起こすためには、どうすればよいのでしょうか。 |
|||||
05-16-2013, 05:55 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
GUI関連のイベント処理順を自力で制御するのは難易度、リスク共に高そうなので、
ボタン押下時と同様のイベントを疑似的に発生させて各種イベントの処理順は システムにおまかせ、という方法が無難ではないかと思います。 プログラムでボタン押下時と同じような動作を行わせるのは、次の手順でできそうです。 1. フォーカスをボタンに移動させる →入力中のテキストフィールドからフォーカスが外れて入力が確定する 2.ボタン押下イベントをイベントキューに積む →イベントキューに積んでいるので、先に行うフォーカス移動に付随して発生する イベントが処理されてからボタン押下イベントハンドラが呼ばれる 一例として、テキストフィールドにIMEで日本語入力中、変換を確定していない状態で、 ショートカットキーで処理を実行した場合でも、GUIのボタンを押した場合と同様に 日本語変換を確定して文字列を取得できるコードを書いてみました。 Code: {value |
|||||
05-17-2013, 07:01 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
説明不足で申し訳ありません。
「ボタンがフォーカスを受け付けない」というのがポイントです。 そのため、ボタン自身のActiveTraverser では、 現在入力されているコントロールからフォーカスを奪えないと思っています。 おそらく、FocusManager を取得し、FocusManager.keyboard-focus-target に対して、 FocusOut イベントを handle-event で発行すればよいのかな、と思っています。 そのためには、ボタンに対して Action イベントが発生した際には、必ず、上記処理を行うように ボタンのhandle-event をオーバーライドする必要があるという認識です。 さらには、FocusOutによって実行させた処理が Dailog を表示するような処理で、 ボタン押下イベントも同様にDialog を表示する処理の場合、 各イベントが個別に走ると、通常ひとつしか表示されないDialogが、複数重なって表示される、 ということがありえるため、 先に実行された処理が終わるまで、ボタンの処理を止めたい、という要望もあると思います。 この問題に対応するためには、dispatch-events が利用できるのではないかと思うのですが、 正確な実装方法がイメージできません。 (そもそも、フォーカスを受け付けないボタンが鬼っ子な気もするのですが・・・) |
|||||
05-19-2013, 02:29 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
失礼しました、例では普通のコマンドボタン使ってしまいましたが状況が違いすぎますね…
ボタンがフォーカスを受け付けないというのがどのような状況かわかっていないのですが、 ご説明ではテキストフィールドの入力確定イベントはそのボタンを押せば起きているよう ですので、おそらくそのボタンはキーボードイベントをハンドルしていないグラフィック オブジェクトなのではないかと思います。 この理解があっていれば、テキストフィールドの外側の背景をクリックしたときと同じ ように、とにかく別のオブジェクトにフォーカスが移動するようにすれば事足りそうな 気もします。(全然、見当違いのとこを言っていたらすみません…) 先のコードのコマンドボタンの代わりにVBoxを使うように直してみました。 勉強不足なもので、お作法的に正しいのかちょっと自信がないですがとりあえず 期待しているようには動きました。 Code: {value >(そもそも、フォーカスを受け付けないボタンが鬼っ子な気もするのですが・・・) 単に見栄えの良いボタン代わりのものをグラフィックオブジェクトで作るとかでしたら 普通にやるだろうなぁと思うのですが、むしろ鬼っ子はこちらのような… >さらには、FocusOutによって実行させた処理が Dailog を表示するような処理で、 Curlではなく他のウィンドウシステムで経験した話になってしまいますが、フォーカス Outのイベントハンドラ内で、同期完了の関数を呼び出してその中でユーザに確認を 求めるダイアログを出すという仕様は鬼門だった覚えが… こちら、ちょっと実験してみます。 |
|||||
05-20-2013, 07:51 AM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
「フォーカスを受け付けない」というのは、「takes-focus?=false」のことを言っていました。
回りくどくてすいません。 handle-event をオーバーライドして、Action イベント時に、 画面内のフォーカスを持っているコントロールに対して、強制的にFocusEventを発行させ、 関連する処理がすべて流れてから Actionの処理を流す、という意図のコードを書いてみました。 dispatch-events がこれで意図通り動くのか、 get-focus-manager で フォーカスマネージャが取得できなかったときにどうすべきかなど、 いろいろ不十分な点がありそうです。 また、たしかに、ボタンでなく、グラフィックでボタンと同様の機能を作るときには、 別途方法を考えなくてはいけないかもですね。 Code: {define-proc public {clean-screen-focus g:Graphic}:void |
|||||
05-20-2013, 01:22 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
フォーカスマネージャを取得する例、いろいろ参考になりました!
察するに、他にも様々な制約が絡んでいる場合の対策を検討されているのですね・・・ 「テキストフィールドの入力確定」というのも自分が考えていたようなIMEの変換中などという単純なことではなさそうな感が・・・ (IMEの変換ならtakes-focus?=falseを設定したボタンでも押せば確定するようですし) もしかすると、ボタンに takes-focus?=false を設定しているのは、Curlドキュメントの「テキスト コントロール内での選択」の 項にあるように、テキストフィールドからフォーカスを移動させないためでしょうか? ボタンがフォーカスを受け付けない、ではなく、テキストフィールドからフォーカスを移動させられない、という事情であれば、 なにか特別な操作が必要になるのも納得です。 (かなりCurlを熟知されているようなので自分なんかの思いつきを書くのは釈迦に説法な感がありますが、以下スレッドタイトルを 見て来た人向けに一応…) 自分が想定していたような、テキストフィールドからフォーカスを移動してもよく、IMEの変換を確定させるだけの単純なケース でしたら、他のオブジェクトにフォーカスを移す方法が簡単で安全な方法な気がします。 takes-focus?=falseに設定されているボタンでも、マウスでクリックすればIMEの変換中でもテキストフィールドは入力確定 するようなので、とくに対策は必要なく、ショートカットキーで呼び出すプロシージャの中でボタンのActionイベントをキューへ 積む前に他のオブジェクトにフォーカス移すだけでよさそうですね。 具体的には、最初に挙げたソースの例でいうと、 || コマンドボタンへフォーカスを移動する {copy-button.become-active-from-traversal} これを次のような感じに変えればよいかと || テキストフィールドの親(VBox等のグラフィックコンテナ)がフォーカスを || 得るようにリクエストして、テキストフィールドのフォーカスを外す {src-tf.visual-parent.request-key-focus} なにか適切でなさそうな所がありましたらご指摘頂けるとありがたいです。 |
|||||
05-21-2013, 04:15 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
はじめまして。
わたしは、umemuraさんとほぼ同じですが、clean-screen-focus の部分を こんな感じで実装しています。 なんとなく。ですが、ValueFinishedとFocusOutを明示的に呼び出すよりも、 manager-release-key-focus を使って、その先の処理はCurlAPIに 任せた方が、後のバージョンアップで問題になりにくそうな気持ちです。 その後、manager-request-key-focus をしているのは、 元の項目に、フォーカスを戻すためで、 TextField入力中に、ショートカットでボタンをActionさせて、 また同じTextFieldで入力が続けられるようにしています。 前提になっているバックグラウンドは、 ショートカットキーでActionが起動されるときに先にFocusOutを発生させたい! というための実装をしていて、 dyoshidaさんのいうところの || イベントキューにコマンドボタンの"Action"イベントを積む {copy-button.enqueue-event {Action}} の代わりに呼び出されるメソッドです。 Code: def cb = [ActionされるCommandButtonです] After 0s の使い方と回数は、これでいいのか?という感じもしますが、 うちではこれで動いてます^^; |
|||||
05-23-2013, 04:16 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
処理の順番を守らせるためにイベントキューへ積むのが目的なら、Kaneko さんの例のように
{after 0s do} を使った方がシンプルかつ応用が効きそうですね、参考になりました。 自分の挙げた例ではFocusOutの後に実行する処理をイベントキューに積むのに、わざわざ グラフィックに Actionイベントハンドラを追加して積んでいましたが、必要なかったですね・・・ |
|||||
05-23-2013, 06:40 PM,
|
|||||
|
|||||
RE: フォーカスを受け付けないボタン押下時に、別テキストフィールドの入力確定を行う
dyoshidaさん、kanekoさん、ありがとうございます。
コメントをいただけると非常にうれしいです。 私の前回のソースでは、ボタンをクリックした後、「マウスを動かさない」ままだと、 処理がそこで止まってしまいました。 dispatch-events true となっているため、クリックした直後に、マウスを動かすなどのイベントがない限り、 次のイベントがくるのを待ち続けてしまう、というのが原因だと思います。 dispatch-events false にすれば動くようにはなったのですが、 「もし、先に流すべきイベントがあれば、そのイベントに関連する処理を先に実行してから、 ボタンのActionイベントに入る」という私の意図に沿った処理になっているか少し不安です。 GuiManager.event-handlers が取得できれば、「現時点で先に流すべきイベントがたまっているかどうか」が わかるのかもしれませんが、このアクセサはプロテクトされているため取得できません。 また、kanekoさんの FocusOut などを利用するのは危ないのでは、というご指摘をヒントに、 コマンドボタンのオーバーライドメソッドを下記のように修正してみました。 こちらのほうが、FocusManager などを取得する必要がないので、シンプルかもしれないですね。 Code: {method public {take-action}:void |
|||||
« Next Oldest | Next Newest »
|
Users browsing this thread:
2 Guest(s)
2 Guest(s)