0

スタックオーバーフロー!

私は、ナビゲーション システムの作成に関するプロジェクトに取り組んでおり、マップの描画とナビゲーション自体の作業を行っている初期段階にあります。すでに描画されている現在のデータの上に正方形を描画できる関数があります。mouseDragged アクション イベントごとに、道路のすべてのデータをもう一度再描画する必要はありません。これを行うには、ガラス板を使用するのが最適な選択であることがわかりました。

問題は、ガラス板の寸法とそれが読み取る座標に関係しています。JPanel (描画に使用) の特定の場所をクリックすると、適切にズームインする方法と場所が認識されますが、正方形を描画すると、マウスの位置よりも特定のピクセル数だけ上に描画されます。これは、ガラス ペインの寸法が JPanel の寸法に対応していないことが原因のようです。JPanel自体はメニューバーで発生したクリックを読み取らないのに対し、ガラスペインはメニューバーも覆っているようです。

どうにかしてガラス板を JPanel に合わせたいと思っており、いくつかの異なることを試しました。私が試したことの 1 つは、JPanel の代わりに JRootPane を描画することでしたが、それは可能ではないようです。次に、JPanel (独自のクラスもあります) から「MyGlassPane」クラスを取得して、再描画メソッドを呼び出そうとしましたが、そこから問題が発生しました。ごく最近、JPanel 自体が使用する、またはその一部である JRootPane を取得してから、この JRootPane のグラスペインを取得しましたが、JFrame に追加されたメニューバーもこの JRootPane の一部であるようです。つまり、ガラス板はメニューバーもカバーしています。

これは、問題をカバーする非常に単純化されたコードですが、マウスのリスニングやデータ描画の側面はカバーしていません。ただし、長方形がメニューバーの上に描かれているのが面倒だという事実を誇示しています。

import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;

public class TestForRootPaneStuff {
    JFrame frame = new JFrame();
    JRootPane root;
    JPanel panel = new JPanel();
    JLabel label = new JLabel("Hello there!");

    public void rootPanePls()
    {
        frame.add(panel);
        panel.add(label);

        root = panel.getRootPane();

        JMenuBar menubar = new JMenuBar();
        JMenu prettyMenu = new JMenu("Pretty");
        menubar.add(prettyMenu);
        frame.setJMenuBar(menubar);

        MyGlassPane gp = new MyGlassPane();
        root.setGlassPane(gp);

        gp.setVisible(true);
        gp.setEnabled(true);
        gp.repaint();


        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(250, 250));

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        TestForRootPaneStuff derp = new TestForRootPaneStuff();
        derp.rootPanePls();
    }

    private class MyGlassPane extends JComponent implements ItemListener
    {
        //React to change button clicks.
        @Override
        public void itemStateChanged(ItemEvent e) {
            setVisible(e.getStateChange() == ItemEvent.SELECTED);
        }

        //Draw the square for zoomToSquare
        @Override
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLUE);
            g.drawRect(10, 10, 100, 100);
        }
    }
}

これは、このコードを実行した結果の対応するスクリーンショットです。(ここでの活動が不足しているため、直接の画像を投稿できません)

私の説明が少なくとも少しは理にかなっていることを願っています。問題を実際に解決するには、私の説明がおそらく少し深すぎることは承知していますが、私の状況と、これに対する解決策が必要な理由について、皆さんにもう少し詳しく説明する必要があると感じました.

TL;DR: JPanel とグラスペインの両方で同じマウス イベント座標を受け取ることができるように、glassPane (どこかから取得/設定) を特定の JPanel のサイズに完全に合わせる方法が必要です。問題の視覚化については、上記のコードを参照してください。これについて賢い方法はありますか?RootPane グラスペインを設定することが私の最終的なアイデアでした...

誰かが何か洞察を持っているなら、前もって感謝します!

キルル~

4

1 に答える 1

2

ここに投稿された間違った/不完全なコードに基づいて推測するだけです。

  1. JComponent の代わりに JLabel を使用します。JComponent には API に LayoutManager がありません。確かに JLabel もそうですが、contianer のように非常に単純なコンテナであり、透過的であり、paintComponent のすべてを (半) 透過的にすることができます

  2. あなたのコードは不完全ですなぜItemListenerがあるのですか、JComponentsをcontianerとしてJComponentに置かないでください、代わりにJPanelを使用してください、または不透明なJLabelがGlassPaneの最も簡単な方法であると述べています、最初のコード行はpaintComponentのsuper.paintComponentでなければなりませんGlassPane に配置/配置されたあらゆるもののペイント

  3. JLabel は、JPanel から座標を簡単にコピーできます。JPanel に追加された ComponentListener を使用し、Swing Timer を使用して ComponentListener から (350-600) イベントを遅延させます (1 ピクセルあたり 1 つのイベントEDIT) </EDIT。サイズ変更が終了すると、Swing Action/ActionListener は、GlassPane に配置された JLabel (何でも) の setBounds を起動します。

  4. GlassPaneのアニメーション用に単純なRepaintManagerを検索します(GlassPaneのJLabels境界をカバーするだけです)

于 2014-03-24T13:04:17.693 に答える