8

これは少し初心者の質問かもしれませんが、私は一生それを理解することはできません。

私はflexを使用して、大規模なプロジェクトのGUI、具体的には下部にあるステータスバーを開発しています。私のStatusBarクラスにはProgressBarがあり、作業を行っている他のクラスは、進行中に更新(バーの完了とラベルの変更)を指示できます。私が直面している問題は、たとえば手遅れになるまで、flexが画面に表示されているものを更新しないことです。

ProgressBarが初期化され、0%完了
いくつかのクラスがProgressBarを12%完了に設定
いくつかのクラスがいくつかの作業を実行
いくつかのクラスがProgressBarを56%完了に設定

何が起こっているのかというと、12%完了は表示されず、作業中は0%でハングし、56%完了までスキップします。フレックスコンポーネントのライフサイクル(無効化と検証)を理解しようとしましたが、理解して正しく適用していると思いますが、まったく機能していません。一部のクラスが12%完了に設定した後、一部のクラスが作業を開始する前に、FlexにStatusBar(または少なくともProgressBar内)を再描画するように指示する必要があります。どうすればよいですか?

4

6 に答える 6

3

グレン、

これは、Flex のスレッド化がまったく機能しない方法です。多くの UI と同様に、メインの UI スレッドにメッセージ ポンプがあります (フレームで実行されます)。callLater()を呼び出すと、渡された関数ポインターがメッセージ ポンプ キュ​​ーの最後 (次のフレーム) に配置され、すぐに戻ります。次に、メッセージ ポンプがすべてのメッセージの処理を終了したときに (マウス クリックなど)、関数が呼び出されます。

問題は、プロパティの変更により UI イベントがトリガーされるため、 callLater()から配置したメソッド呼び出しの後にポンプに独自のメッセージを配置することです。

Flex には複数のスレッドがありますが、それらは Adob​​e 独自の理由で存在するため、ユーザーがアクセスすることはできません。特定の時点で UI の更新が発生することを保証する方法があるかどうかはわかりませんが、操作が発生するまで何度もcallLaterを呼び出すオプションがあります。小さい数から始めて、必要な結果が得られる反復回数まで増やします。例:

// Change this to a number that works... it will probably be over 1, depending on what you're doing.
private const TOTAL_CALL_COUNT:int = 5;

private var _timesCalled:int = 0;

//----------------------------------------------------------------
private function set Progress( progress:int ):void
{
    progressBar.value = progress;
    DoNextFunction();
}

//----------------------------------------------------------------
private function DoNextFunction():void
{
    if( _timesCalled >= TOTAL_CALL_COUNT )
    {
        _timesCalled = 0;
        Function();
    }
    else
    {
        _timesCalled++;
        callLater( DoNextFunction );
    }
}
于 2010-05-10T21:09:12.090 に答える
2

Flash Player の Actionscript は、ブラウザーの Javascript と同様に、疑似マルチスレッド化されています。つまり、それらはシングル スレッドですが、複数の実行スタックがあります。これは、特定のスレッドで「スリープ」することはできませんが、後で延期される新しい実行スタックを生成できることを意味します。これを柔軟に行う方法は、「c​​allLater」関数です。setTimeout/setInterval 関数を使用することもできます。または、Flash Player に組み込まれているタイマー オブジェクトを使用することもできます。または「ENTER_FRAME」イベントリスナーですら。あなたの問題の原因について私が正しければ、これらのすべてが本質的にあなたが必要とすることを可能にします.

1 つの「スレッド」がほとんどの作業を行っており、他の実行スタック (スレッド*) の実行を許可するために停止することはないようです。

問題は PeZ が言っていることかもしれませんが、それでも解決しない場合は、ワーカー クラスの遅延呼び出しを試してみてください。したがって、プロセスは次のようになります。

  1. 進行状況が初期化されました。
  2. いくつかの作業を行います。
  3. プログレスバーを 12 に更新します。 (表示リストを無効にします)
  4. setTimeout(doMoreWork, 100);
  5. プログレス バーを 52 に更新します。

(ワーカーが UIcomponent の場合、uicomp.callLater(...) を使用できます。それ以外の場合は、純粋な AS3 クラスに対して setTimeout/timers/enter_frame を使用する必要があります)。

于 2009-07-13T22:02:47.390 に答える
2

プログレスバーが変更されるたびに、invalidateDisplayList() を呼び出してみてください。何かのようなもの :

Class StatusBar
{

    public function set progress(value:uint):void
    {
        progressBar.value = value;
        progressBar.invalidateDisplayList();
    }
}

Flex には、プロパティが変更されるたびに画面が再描画されるのを回避する無効化サイクルがあります。例として、プロパティの値が 1 つのフレームで 3 回変更された場合、最後に設定された値でのみレンダリングされます。コンポーネントを強制的に再描画するには、invidateDisplayList() を呼び出します。これは、updateDisplayList が次のフレームを待たずにすぐに実行されることを意味します。

于 2009-07-13T20:21:31.697 に答える
1

別の値を割り当てる前にゼロに設定する必要がある場合があります。progressBar.setProgress(0、progressBar.maximum); progressBar.setProgress(newValue, progressBar.maximum);

于 2015-04-15T00:02:07.030 に答える
0

Flash Builder 4.6 を使用していますが、進行状況バーの表示にも問題があります。新しいマルチローダー クラス (39 Mo のコンテンツ) を開始する新しいウィンドウを開きます。新しいウィンドウがバックグラウンドで開かれ、マルチローダー クラスが作業を完了するまで、メイン ウィンドウにプログレス バーが表示されます。ただし、オープニング ウィンドウがメイン ウィンドウのアニメーションをブロックしています。マルチローダークラスではないことはわかっていますが、正しく実行されていることがわかりました。

しかし、私はそれを行うためのいくつかの新しい方法を見つけようとします。

私の投稿の主な目的は、アドビがフラッシュを中心に構築した複雑さです。独自のアプリケーションや質問に対する回答のリソースを探す場合、適切なリソースを見つけるのは非常に困難です。AS3、Flex、Flash CS、Flash Builder、AiR などの間には (adobe 側とユーザー側で) 完全な混同があります。AS3 で開発しようとすると、いくつかの例が機能しないことがわかります。 SDK に実装されていないためです。さまざまな開発プラットフォームでの経験に基づいた「ベスト プラクティス」または皮肉な回答を提供するフォーラムがますます増えています。

例として、上記のように、progressBar.value = value; と表示されます。私の経験から言えば、Flash Builder 4.6 では、このプロパティは読み取り専用です。しかし、それはユーザーによって作成されたカスタムクラスかもしれませんが、誰が知ることができます.

于 2013-12-23T09:02:09.407 に答える