1

AS3 では、stage.focus はフォーカスのある表示オブジェクトを取得/設定します。フォーカスは、InteractiveObject インスタンスと、TextField、Sprite、MovieClip など、そのインスタンスから継承されるすべてのものに割り当てることができます。

ちなみに、これが ECMAScript 仕様の一部であるかどうかを調べたところ (AS3 と JavaScript には共通点があるため)、JavaScriptではフォーカスの管理 (特にフォーカスの取得) がはるかに難しいことがわかりました。古いブラウザは document.activeElement プロパティをサポートしておらず、新しいブラウザでも入力関連の要素のみを返すように制限されています。そのような要素にフォーカスがない場合、すべての主要なブラウザーは body 要素を返します - html 要素を返す IE 9 を除き、Chrome 26 は XHTML ドキュメントで false を返しますが、明らかに document.querySelector(':focus') を使用できます。

JavaScript とは対照的に、AS3 はどの InteractiveObject もキーボード フォーカスを受け取ることができるという点で非常に均一で一貫性があることを発見しました。ただし、デフォルトでは、オブジェクト (TextField および SimpleButton インスタンスを除く) は、マウスまたはキーボードの操作によってフォーカスを受け取りません。

最初にイベント リスナーをステージにアタッチして FocusEvent.FOCUS_IN イベントをリッスンしたとき、ステージ上で作成した MovieClip オブジェクトをクリックしてもイベント リスナーが起動しませんでした。デフォルトでは、クリックまたはタブ移動によってステージ フォーカスを受け取りません。

一方、tabEnabled または buttonMode プロパティを true に設定すると、オブジェクトがクリックされたときにイベントが発生します。ちなみに、tabEnabled のドキュメントには、Sprite.buttonMode が true の場合に自動的に true になると記載されているため、tabEnabled は関心のあるプロパティのようです (また、buttonMode は、Enter キーまたはスペース キーが押されたときにクリック イベントをトリガーするなど、他の機能も有効にします。オブジェクトにフォーカスがあります)。

クリックしたときに対話型オブジェクトがステージ フォーカスを確実に受け取るようにするための正しい方法は、tabEnabled であるかどうか疑問に思っていました。tabEnabled のドキュメントには、オブジェクトが [キーボード] タブの順序に含まれると書かれていますが、特にマウスの操作については言及されておらず、「フォーカスを受け取ることができる」などの一般的な状態についても言及されていません。stage.focus をそのオブジェクトに設定することにより、インタラクティブなオブジェクトに手動でフォーカスを割り当てることができるようです。

InteractiveObject の「tabEnabled」プロパティが、キーボードとマウスの両方を介した対話を通じてフォーカスを割り当てることができるかどうかを制御する主要なプロパティであることは正しいですか?

JavaScript では、HTML5 仕様は、オブジェクトが「フォーカス可能」と見なされるために満たす必要がある、より複雑な一連の条件を示しています。 2. 要素はレンダリングされているか、埋め込みコンテンツを表す canvas 要素の子孫です. 3. 要素はinertではありません. *要素は無効化されていません."

更新: よく調べてみると、AS3 には一般的な「有効な」プロパティはありませんが、「mouseEnabled」は同様に機能するようです。これは、false に設定すると、「インスタンスはマウス イベント (またはキーボードなどの他のユーザー入力イベント) を受信しないためです」イベント)」。

最初の更新の更新: 「(またはキーボード イベントなどの他のユーザー入力イベント)」というフレーズを含めることにより、ドキュメントは間違っています。これは、mouseEnabled が false に設定されているにもかかわらず、フォーカスされたオブジェクトがキーのダウン/アップ イベントを受け取るためです。

4

3 に答える 3

1

ご想像のとおり、InteractiveObject がユーザー入力を通じてフォーカスを取得できるようにするために設定する必要があるのはtabEnabledプロパティですが、わかりやすくするために、私の答えを少し拡張します。

InteractiveObject は、そのプロパティに関係なく、フォーカスを持つことができます。ただし、フォーカスを取得する方法とフォーカスの位置を決定するプロパティがいくつかあります。

  • Stage.focusは、現在どの InteractiveObject がフォーカスされているかを示します。このメソッドは読み取り専用ではありません。設定すると、指定された InteractiveObject にフォーカスが切り替わります。アプリケーションでフォーカスを処理する方法をプログラムで変更すると便利です。
  • InteractiveObject.tabEnabledインスタンスがユーザーの操作によってフォーカスを受け取ることができるようにします。クリック、タブ、および矢印キーの使用を意味します。このプロパティでは、インスタンスがユーザー入力を受信できないことに注意してください。ステージがこのインスタンスにフォーカスを与えることのみを許可します。
  • InteractiveObject.tabIndexを使用すると、アニメーションを通じてタブ オーダーを設定できます。タブ移動のみに適用されます。矢印キーを使用すると、これは無視されます。
  • InteractiveObject.mouseEnabledはフォーカスとは関係ありません。インスタンスがマウス イベントを受信できるようにします。

AS3 でフォーカスがどのように機能するかをよりよく理解するために、オブジェクトがフォーカスを取得するのではなく、フォーカスが与えられていると言えます。フォーカスはステージによって管理されます。tabEnabled は、オブジェクトにフォーカスを与える必要があるかどうかをステージが認識するためのインジケーターです。

補遺 : ほとんどの InteractiveObject はフォーカスを必要としないと AS3 が推定するため、tabEnabled プロパティはデフォルトで false です。結局のところ、オブジェクトはフォーカスを必要とせずにクリックを受け取ることができます。

于 2014-05-13T08:45:57.513 に答える
0

すでに別の投稿を回答としてマークしていますが、追加情報を追加したかっただけです。

FocusEvent.MOUSE_FOCUS_CHANGE および FocusEvent.KEY_FOCUS_CHANGE は FOCUS_IN および FOCUS_OUT イベントに先行し、FOCUS_IN/OUT イベントとは異なり、キャンセル可能です。

さらに重要なのは、ターゲット オブジェクトと関連オブジェクトの両方が MOUSE_FOCUS_CHANGE イベントで読み込まれる (つまり、null でない) ことです。一方、クリックされたオブジェクトの tabEnabled 値が false の場合、直後の FOCUS_OUT イベントには null 関連オブジェクトが含まれます。

ステージのキャプチャ フェーズで MOUSE_FOCUS_CHANGE および KEY_FOCUS_CHANGE イベントを処理することにより、フォーカス変更システム全体のデフォルトの動作をオーバーライドし、マウス クリックの結果としてフォーカスが null になるのを防ぐことさえできます。

たとえば、オブジェクトをクリックしたときのデフォルトの動作 (tabEnabled が true か false かに関係なく) では、現在フォーカスがあるオブジェクトとクリックされたオブジェクトを含む MOUSE_FOCUS_CHANGE イベントが発生します。次に、条件付きで:

  • クリックされたオブジェクトに tabEnabled = true が設定されている場合、フォーカスが割り当てられ、FOCUS_OUT/IN イベントにより、ターゲット オブジェクトと関連オブジェクトの両方が取り込まれます。
  • 一方、クリックされたオブジェクトの tabEnabled = false が設定されている場合、フォーカスは null に設定され、FOCUS_OUT イベントには null 関連オブジェクトが含まれます。

したがって、tabEnabled の値に依存するデフォルトの動作をキャンセルする場合、tabEnabled が false であっても関連オブジェクトに常に手動でフォーカスを割り当てることを選択できます。そのため、マウス クリックは引き続き FOCUS_OUT イベントをトリガーしますが、それらはnull 関連オブジェクトを持つことはありません。

同様に、キーボードによるフォーカス変更のデフォルトの動作をオーバーライドできます。私の KEYBOARD_FOCUS_CHANGE イベント ハンドラーは、カスタム フォーカス ループ配列のプッシュ可能/ポップ可能なスタックを維持するクラスに基づいているため、タブが押されると、現在フォーカスされているオブジェクトがアクティブかどうかをチェックします。スタックの一番上にあるループ (またはアクティブなループ内のオブジェクトの子/孫) であり、そうであれば、次のインデックス位置 (Shift キーが押されている場合は前の位置) にあるオブジェクトにフォーカスを割り当てます。オブジェクトがループ内にない場合、(設定に基づいて) スタックの一番上にあるアクティブなループ内の最初のオブジェクトにフォーカスが自動的に割り当てられます。フォーカスがループを離れるのを防ぐこともできます (フォーカス オブジェクトがループ内にあるか、ループ内のオブジェクトの子孫である必要があります)。ループはパブリック メソッドを介して変更でき、さまざまなコントロール セットを含むダイアログ ウィンドウを開いたり閉じたりするときに、定義済みのコントロール セットを割り当てることができます。コントロールの新しい配列をダイアログ ウィンドウのスタックにプッシュすると、現在フォーカスされているオブジェクトと現在のフォーカス配列がバックアップされ、フォーカスが新しい配列に移動されます。スタックをポップすると、古い配列が復元され、バックアップ時にフォーカスがあったオブジェクトにフォーカスが戻ります。それはすべて非常にうまく機能し、デフォルトのメカニズムよりもはるかに正確で制御可能です.

私が作成したフォーカス マネージャーには「nullFocus」プロパティもあり、フォーカスが null になる場合に特定のオブジェクトをフォーカスを持つオブジェクトとして指定できるため、フォーカスが実際に null になることはなく、イベントは常に処理可能です。 .

于 2014-05-20T16:46:28.543 に答える
0

これは古い質問であることは承知していますが、クライアントから新しいリクエストがあったため、しばらくの間フォーカスの切り替えについて調査してきました。彼らは、テンキーの + キーがタブのように機能し、テキスト ボックス間でフォーカスを変更できるようにしたいと考えていました。

私がそれをどのように達成したかは、初期のプログラミング時代に確立したいくつかの策略によるものでした。

テキスト ボックスを生成する関数を作成しました (以下)。

function mkText(xpos,ypos,h,w,l:int,multi,sel,bor:Boolean,borCol:uint):TextField{

        var textInput = new TextField();
        textInput.x = xpos;
        textInput.y = ypos;
        textInput.height = h;
        textInput.width = w;
        textInput.maxChars = l;
        textInput.multiline = multi;
        textInput.selectable = sel;
        textInput.border = bor;
        textInput.borderColor = borCol;
        addChild(textInput);
        return textInput;
    }

これにより、次のように、配列を使用してループ内にテキスト フィールドを作成できます。

    for(var i:int=0;i<8;i++)
{
    cForm[i] = mkText(cFormXpos,cFormYpos,27,69,2,false,true,true,0x000000);
    cForm[i].type = TextFieldType.INPUT;
    cForm[i].restrict = "0-9";
    cForm[i].defaultTextFormat = txFormat;
    cFormYpos += cForm[i].height + 13;
}

ループを実行するたびに、動的に割り当てられたインスタンス名を持つ新しいテキスト フィールドが作成されます。たとえば、instance1、instance2 など、配列の任意の要素の名前をトレースすると確認できます。これらのそれぞれは、それらの配列の位置もバッチでフォーマットされたり、個別に参照されたりします。このアプローチでは、インクリメンタと一般的な stage.focus 属性を使用してそれらを切り替えました。

function keyBind(e:KeyboardEvent)
{
    if(e.keyCode == 107)
    {
        stage.focus = cForm[tabOrder];
        if(tabOrder < 8)
        {
            tabOrder++;
        }
        else
        {
            tabOrder = 0;
        }
    }
}

より複雑な問題に対するやや大雑把な解決策であることは理解していますが、割り当てられたインデックスにより、タブのような処理を簡単に実現できます。

これが役立つことを願っています。

乾杯

ps。微妙なスペルミスをお詫びします。私はこれを非常に素早く入力し、数回編集する必要がありました.

于 2015-11-04T15:14:56.300 に答える