3

リスナーから何度もリペイントを呼び出していますが、ペイント関数を設計した方法は、1回のリペイントで済みます。マウスモーションリスナーに接続されているため、大量の再描画を生成します。

特定のコンポーネントの保留中のすべての再描画をキャンセルする方法はありますか?フレームのサイズを変更したり、最小化から復元したりする場合のように有効なものもあるため、再描画を無視し始めることはできません。

なぜ気にするのですか?私のペイントコードは非常に重く、非常に高いFPSでは完全な再ペイントを行うことができないためです。

4

5 に答える 5

2

頻繁な再描画要求は自動的に1つにまとめられます。これを最適化する最良の方法は、全体を再描画するのではなく、特定の領域の座標を使用して再描画を呼び出すことです。これは、実際に変更された領域のみを再描画することを意味します。

于 2009-08-10T19:08:51.257 に答える
2

Swingは、リペイントを組み合わせます。SunのWebサイトの「PaintinginAWTandSwing」を参照してください。多数の再描画をすばやく連続してスケジュールすると、それらは、paintImmediately()への1回の呼び出しに結合されます。

于 2009-08-10T19:09:27.730 に答える
1

私の理解ではrepaint()、コンポーネントの領域を再描画キューに追加することで、再描画をスケジュールするだけです。コンポーネントで既に再描画が要求されている場合、新しい再描画領域は以前に要求された領域と結合されます。再描画は、イベントキュー内の他のすべてのイベントが処理されるまで実際には実行されません。したがって、追加の再ペイントは大きな違いをもたらさない可能性があります。つまり、ペイントコードは1回だけ実行されます。JComponent.repaintおよびRepaintManager.addDirtyregionを参照してください。

于 2009-08-10T19:08:42.973 に答える
0

あなたの言うことを聞きます。実際、領域の一部のみを再描画できます。SunのWebサイトの「カスタムペイントの例の実行」で、ドラッグした長方形を描画し、マウスを動かしたり離したりしたときにのみその領域を再ペイントする方法を示す便利な例を見つけました。

これがコードの関連セクションです...

public void mouseDragged(MouseEvent e) {
            updateSize(e);
        }

        public void mouseReleased(MouseEvent e) {
            updateSize(e);
        }

        /* 
         * Update the size of the current rectangle
         * and call repaint.  Because currentRect
         * always has the same origin, translate it
         * if the width or height is negative.
         * 
         * For efficiency (though
         * that isn't an issue for this program),
         * specify the painting region using arguments
         * to the repaint() call.
         * 
         */
        void updateSize(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            currentRect.setSize(x - currentRect.x,
                                y - currentRect.y);
            updateDrawableRect(getWidth(), getHeight());
            Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
            repaint(totalRepaint.x, totalRepaint.y,
                    totalRepaint.width, totalRepaint.height);
        }

このコードは著作権の対象です(完全なコードと著作権表示についてはこちらをご覧ください)

さらなる例のリストについては、ここを参照してください

正直なところ、FPSでも同様の問題が発生していますが、それは現在のコードが貧弱なことが原因である可能性があります。過去数か月で多くのことを学び、コードをより効率的にすることができるようになりました。うまくいけば、2人以上の「人」が私のグラフィックを遅くしたときにFPSの問題を克服することができます!うーん...私は自分のコードの同じセクションに上記のコードを実装しただけで、他のコードは実装していませんが、ぜひ試してみてください!

于 2009-08-13T23:05:59.093 に答える
0

JFreechartが再ペイントを何度も呼び出すときに、JFreechartがペイントを決定する方法を改善するために、似たようなものを一緒にハックしました。

基本的に私は次のことを行います。

  • ScheduledExecutorServiceクラスのフィールドとしてを作成します
  • 最初の再描画リクエストを受信し、submitそれをエグゼキュータに送信して、EDTで実行し、たとえば50ミリ秒で未来を取り戻します
  • 2番目の要求を受信します-前の再描画が終了したかどうかをテストし(fut.isDone())、終了した場合は次の再描画をスケジュールします。それ以外の場合は何もしません。

このようにして、1秒あたり最大20回の再描画要求を受け取る必要があります。

fireDataTableChanged同時に多くの変更が発生する場合に、呼び出しの数をバッチ処理するために同様のことを行いました。

于 2009-08-10T19:15:21.290 に答える