画面の操作を無効にするには? - umemura - 02-26-2014
ある処理の間、画面の操作を無効化したいです。
lib ライブラリに、ボタンの2度押し防止のためのAPIとして、
with-busy-view があり、これを使うと、
TextField なども操作不可の状態になるので、
画面をロックする目的に利用できるかな、と思ったのですが、
①with-busy-view を呼び出す
②上記の処理中に、画面上のテキストエリアをクリック
③キー入力を行う
↑このタイミングでは画面上には入力したキーは表示されない
④with-busy-view の処理が終了する
⑤画面上のテキストエリアに、先ほど入力したキーが表示される。
となってしまい、目的に合致しません。
おそらく、with-busy-view の処理中も、マウスイベント、
キーイベントがイベントキューにたまり
with-busy-view の処理が終了したら、イベントキュー内のイベントが順次実行されてしまうため、
この現象になっていると思っています。
理想は、⑤の時点で、それまでの全てのイベントを破棄してほしいです。
画面の操作をロックする方法をご存知の方がいらっしゃったら教えてください。
Code: {import * from COM.CURL.LIB.UI}
{def v:View = {View}}
{def ta = {TextArea
width = {make-elastic},
height= {make-elastic}
}}
{def cb =
{CommandButton
label= "with-busy-view",
{on Action do
{with-busy-view v do
||時間をかけるためのダミー処理
def (buf:StringBuf, n:int, encoding:CharEncoding) =
{read-from {url "http://www.yahoo.com"}}
}
}
}
}
{do
{v.add {VBox hstretch? = true, ta, cb}}
{v.show}
}
RE: 画面の操作を無効にするには? - umemura - 02-26-2014
画面にバリアを張って、バリア解除時にイベントを破棄すれば出来そう・・・。
Code: {import * from COM.CURL.LIB.UI}
{define-class public BarrierFrame {inherits OverlayBox}
{constructor public {default ...}
{construct-super {splice ...}}
set self.barrier-screen-frame =
{Fill background = "transparent"}
}
||処理中に画面をロックするためのバリア
field barrier-screen-frame:Graphic
field private _barrier?:bool = false
{getter public {barrier?}:bool
{return self._barrier?}
}
{setter public {barrier? val:bool}:void
set self._barrier? = val
{if self._barrier? then
||バリアーを張る
{self.add self.barrier-screen-frame}
else
||バリア解除時に、それまでのイベントを破棄する
{dispatch-events false}
{self.barrier-screen-frame.detach}
}
}
}
{def v:View = {View}}
{def bf = {BarrierFrame}}
{def ta = {TextArea
width = {make-elastic},
height= {make-elastic}
}
}
{def cb =
{CommandButton
label= "with-busy-view",
{on Action do
{with bf.barrier? = true do
{with-busy-view v do
||時間をかけるためのダミー処理
def (buf:StringBuf, n:int, encoding:CharEncoding) =
{read-from {url "http://www.yahoo.com"}}
}
}
}
}
}
{do
{v.add bf}
{bf.add {VBox hstretch? = true, ta, cb}}
{v.show}
}
RE: 画面の操作を無効にするには? - alchimiste - 03-12-2014
umemuraさんのBarrierFrameを使って、新しいwith-busy-new-viewマクロを作ってみました。
with-busy-new-viewの呼び出しだけで、バリア効果が出ます。
Code: {define-macro public
{with-busy-new-view
?view:expression
do
?body:verbatim
}
{return
{expand-template
|| ?viewはGraphic客体に変更
let g:Graphic = ?view
|| 追加されたコード
|| umemuraさんのBarrierFrameを利用
let view:View = {g.get-view} asa View
let b:#BarrierFrame
{for child in view.ordered-children do
{type-switch child
case t:BarrierFrame do
set b = t
else
set b = {BarrierFrame}
{b.add child}
{view.add b, replace?=true}
}
{break}
}
def restore-proc = {disable-buttons view}
{try
{with b.barrier? = true do
{view.update}
?body
}
finally
{after 0s do
{restore-proc}
|| FIXME:
|| スキンコントロールで正しく再描画されない場合があるためのworkaround
{refresh-skin-drawing view}
}
}
}
}
}
次は使用の例です。より簡単なコードになりました。
Code: {def ta = {TextArea
width = {make-elastic},
height= {make-elastic}
}
}
{def cb =
{CommandButton
label= "with-busy-view",
{on Action at c:CommandButton do
{with-busy-new-view c do
||時間をかけるためのダミー処理
def (buf:StringBuf, n:int, encoding:CharEncoding) =
{read-from {url "http://www.yahoo.com"}}
set ta.value = {buf.to-String}
}
}
}
}
{def box = {VBox hstretch? = true, ta, cb}}
{value box}
|