0

OpenGL を使用していくつかの 3D 関数 (f(x,y)) を描画する Android 用の最初の Java プログラムを作成しました。プログラムはほぼ完成しましたが、LinearLayout (作成したもの) として開発されたカスタム プログレス バーの表示と非表示で問題が発生します。テキストとプログレスバー付き。3dfunction 値の計算前および計算中に、progressBarLL を表示する必要があります。これを行うために、Graph3dActivity にハンドラーを実装しました。

public class Graph3dAct extends Activity {
    (...)
    static ProgressBar progressBarPB;
    static LinearLayout progressBarLL;
    public static Handler progressHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.e("HANDLER:",Integer.toString(msg.arg1));
            //toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 500);             
            switch (msg.arg1)
            {
            case 1: progressBarLL.setVisibility(LinearLayout.VISIBLE);
                    break;
            case 2: progressBarLL.setVisibility(LinearLayout.INVISIBLE);
                    break;
            case 3: progressBarPB.setProgress(msg.arg2);
                    //to be implemented
                    break;
            default: Log.e("Graph3dAct","Handler misused;");
            }
            progressBarLL.invalidate();
            progressBarPB.invalidate();           
      }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);
        (...)
        progressBarPB = (ProgressBar) findViewById(R.id.surface3dPB);
        progressBarLL = (LinearLayout) findViewById(R.id.progressLL);
        (...)
        final Button moreStepsB = (Button) findViewById(R.id.buttonMoreS);
        moreStepsB.setOnClickListener(new View.OnClickListener() {          
            @Override
            public void onClick(View v) {  
                int max=stepsVals.length-1;
                if (stepsIndex<max) 
                {
                    stepsIndex++;
                    steps=stepsVals[stepsIndex];
                    FuncSurf fs = new FuncSurf(steps);
                    renderer.funcSurf =  fs;

次に、FuncSurf とそのコンストラクターを使用して、サーフェスの長期的な計算を行います。計算の前に、progressBarLL を表示する必要があります。

public class FuncSurf {
    public FuncSurf(int steps_) {        
            Log.e("FuncSurf","CONSTRUCTOR");
            Message msg = new Message();
            msg.arg1=1; //instruct handler to show progress layout: progressBarLL
            Graph3dAct.progressHandler.sendMessage(msg);

            (...) HERE GOES LONG-LASTING CALCULATION        

            msg = new Message();
            msg.arg1=2; //instruct handler to hide progress layout: progressBarLL
            Graph3dAct.progressHandler.sendMessage(msg);    
    }

問題は、上記のアクティビティで実装された onClick イベントから関数 FuncSurf コンストラクターを呼び出すと、progressBarLL が非常に短時間表示され、計算が完了する前ではなく残念ながら表示されることです。つまり、ハンドラーは FuncSurf コンストラクターが同時にではなく終了した後にメッセージを処理します。同じスレだからかな?しかし、Renderer から FuncSurf() コンストラクターが呼び出されると、すべて問題ありません。

class MyOpenGLRenderer implements Renderer {
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            funcSurf = new FuncSurf(steps); //progressBarLL shown OK

私の質問は、このコンストラクターを呼び出す場所に関係なく、 FuncSurf() コンストラクターの計算の前に progressBarLL が表示されるように、コードをきちんと修正する方法です。上記の onSurfaceChanged(...) によって呼び出されたとき、これは GUI スレッドではないため、funcSurf で progressBarLL.setVisibility を直接使用することはできません。申し訳ありませんが、問題を明確に説明できませんでした。私はあなたの助けを楽しみにしています。

4

2 に答える 2

0

そんな中、ひとまず問題を解決してくれる「スレッド構築」を見つけました。別のスレッドで「長時間タスク」の実行を強制し、GUI スレッドが継続して Handler によって GUI を更新できるようにします。コードの最初の部分を少し変更すると、プログラムは正常に動作するようになりました。

Runnable run = new Runnable() 
{
    @Override
    public void run() {
        FuncSurf fs = new FuncSurf(steps);
        renderer.funcSurf =  fs;
    }
};       
Thread thr = new Thread(run);
thr.start();
于 2014-06-03T09:54:21.107 に答える