1

多数の円 (Ellipse2D) で満たされたパネルがあります。円は 2 次元配列 (行と列) に格納されます。

私の目標は、マウスを円の上にドラッグするときに円を「ペイント」できるようにすることです。最終的には、選択図形に含まれるすべての円の色を変更する選択図形を使用したいと考えています。

2次元配列全体を継続的にスキャンし、現在の点が円の内側にあるかどうかを確認するマウスドラッグリスナーを使用しています。そのようです:

        addMouseMotionListener(new MouseAdapter() {

        public void mouseDragged(MouseEvent e) {

            currentColor = ColorSliderPanel.getRGB();

            for (int x = 0; x < numColumns; x++) {
                for (int y = 0; y < numRows; y++) {
                    if (circle[x][y].contains(e.getX(), e.getY())) {

                        circle[x][y].setColor(currentColor);
                        repaint();
                    }
                }
            }

        }
    });

上記のコードは機能しますが、すべてのオブジェクトをチェックしているため、非常に低速です (1000 円以上)。

もっと良い方法があるはずです。四分木について少し読んだことがありますが、四分木が必要以上の馬力を持っているかどうかはわかりません。

ありがとう

以下のコメントのいくつかに基づいて、次の変更を加えました。Circles は線形の ArrayList になりました。draw メソッドは単純に円を塗りつぶします。この変更により、速度が 2 桁向上しました。今でははるかにうまく機能します。ただし、パネルを適度な速度でスイープして、いくつかの円を逃すことはできます。したがって、さらに最適化する必要があるかもしれません。

  Graphics2D g2d = (Graphics2D) getGraphics();

            for (Circle2D c : circles) {
                if (c.contains(p)) {
                    c.setColor(currentColor);
                   //Graphics2D g2d = (Graphics2D) getGraphics(); (moved)
                    c.draw(g2d);
                }
            }
4

4 に答える 4

3

私が個人的にこれを行う方法は次のとおりです。

  • 円の線形配列 (またはリンクされたリスト、選択したもの) を作成します。
  • イベントリスナーでは、配列を線形に反復し、マウスの位置に対してすべての円をヒットテストし、テストが成功した場合は色を変更します
  • 最大の最適化は次のとおりです。かなり高い頻度で (マウスを動かすたびに) 描画することについて話しているため、どの円再描画する必要があるかを判断する必要があります。上記の配列を繰り返し処理しているときは、変更する必要がある最大のバウンディング ボックス(再描画する必要があるすべての円を囲む四角形)の実行中のカウントを保持します。
  • ここで、上で計算した四角形を削除し、再び円を反復処理して、四角形の内側にある円のみを描画します (特定の円を切り取る可能性がありますが、四角形の内側に収まり、外側に触れないようにすべてを描画します)。

注: 1k以上の円を2回反復すると、ほぼ瞬時になります。実際の問題は、円の描画(および奇妙なx / yストレージメカニズム)にあります。グラフィック I/O は、特に Java の方法では遅くなります。

さらなる最適化は、メモリ ビットマップを作成し、そこに長方形を描画してから、メイン サーフェスで一度にすべてブリットして、ちらつきをさらに減らすことです (これは、更新のたびに再描画パスが遅いために発生します)。

于 2010-02-14T00:07:00.633 に答える
1

数千のメソッド呼び出しは、現代のコンピューターでは 10 マイクロ秒程度かかりますが、これは人間が認識できるほどの遅延ではなく、ましてや「非常に遅い」ことは言うまでもありません。

したがって、パフォーマンスの問題の原因は別の場所にあるはずです。おそらく repaint() にあり、コンテナの paint() が呼び出されます。これで 1000 個の円を数個描画すると、1 秒近くかかることがあります。

これが、最適化する前に、パフォーマンスのボトルネックが実際にどこにあるかを常に測定する必要がある理由です。

于 2010-02-14T00:03:57.160 に答える
1

を呼び出すたびに円のセット全体を反復処理するのmouseDraggedは、信じられないほどの時間の無駄です。選択肢の 1 つはJTableMouseEvent. 列の幅と行の高さがわかっている場合は、円のセルを識別するのはそれほど難しくありません。

于 2010-02-14T00:04:35.833 に答える
1

このでは、境界の四角形をドラッグして選択できる、移動可能でサイズ変更可能な色付きのノードが特徴です。実装では、長方形の境界線を表示して、選択したノードを強調表示します。下の図では、緑と黒のノードが選択されています。代わりに色を変更すると、 のdraw()方法を簡単に変更できNodeます。

グラフパネル

于 2010-02-14T01:25:57.457 に答える