8

ScrollPane を使用してビューポートに画像を表示し、画像上にグリッド (またはボックス、またはその他の種類の登録/位置マーカー) オーバーレイを配置したいと考えています。スクロール時にオーバーレイを固定したままにする必要があります(画像がオーバーレイの「下」に移動するように見えることを意味します)。ビューポート内のビューを固定速度でスクロールして滑らかな動きを提供し、オーバーレイはビューポート内の特定の場所への参照を提供します。概念的には、Viewport 内でスクロールする大きな地図と、(Viewport 自体に対して) 移動しない四角形を持つ Viewport を考えてみてください。この四角形は、何らかのユーザー アクションに基づいてズームインできる領域をマークします。

私は、ScrollPane の実装が View のレンダリングを効率的に処理し (バッキング ストアから、新しい部分的な露出ごとに View 全体 (または ViewPort でさえも) を再描画する必要がない) を処理することを想定しています (ただし、まだ確認していません)。 paint() メソッドをオーバーライドします。

私は LayerPane を見てきましたが、それを習得していませんが、これは力ずくのアプローチのようです。ScrollPane は SplitPane の 1 つのコンポーネントであり、移動/サイズ変更されます。絶対配置を使用して、ViewPort と LayerPane の間の正しい関係を手動で維持する必要があると思います。私は GUI の設計と実装の専門家とはほど遠いので、経験豊富な人が知っている明らかなものからあいまいでエレガントなものまで、さまざまな可能性を見逃していると確信しています。

私が始めた道だけでなく、どんな提案も受け入れます。JPanel を SplitPane の 1 つのコンポーネントとして追加してから、LayerPane を、ScrollPane と LayerPane の異なるレイヤーにあるオーバーレイ (別の JPanel) を含むコンポーネントに追加する必要がありますか? これを直接サポートする ScrollPane の機能はありますか? Java Swing チュートリアルと API ドキュメントを見てきましたが、まだ何も見ていません。

ありがとう。

アップデート:

リンクをありがとう、トラッシュゴッド。これは私が予想していたよりもはるかに簡単でした。LayerPane、GlassPane、xor ベースの合成は必要ありません...オーバーレイを描画するために JViewport.paint() をオーバーライドしようとしなかった理由はわかりませんが、以下のコードを使用して、概念が検証されることを確認しました私が探しているものをください。JViewport のサブクラスを使用するだけで、私が望んでいたことを実行できます (この場合、画像が下にスクロールしている間、Viewport の中央に四角形をオーバーレイします)。私は GUI の専門家ではありません。Java API は信じられないほど幅広いものです。皆さんがどうやってこのことを頭に入れているのかわかりませんが、ありがとうございます!

class MyViewport extends JViewport {
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLACK);
        g2.drawRect(getWidth()/4,getHeight()/4,getWidth()/2,getHeight()/2);
    }
}
4

1 に答える 1

7

AWT と Swing でのペイント: ペイント メソッド で説明されているように、通常、「Swing プログラムはオーバーライドpaintComponent()ではなくオーバーライドする必要があります」 。スクロール コンテンツの下に描画するに基づいて、次の例は、スクロール コンテンツのに描画するようにオーバーライドします。paint()ScrollPanePaintpaint()

スクロールペインペイント

import java.awt.*;
import javax.swing.*;

/**
 * @see https://stackoverflow.com/a/10097538/230513
 * @see https://stackoverflow.com/a/2846497/230513
 * @see https://stackoverflow.com/a/3518047/230513
 */
public class ScrollPanePaint extends JFrame {

    private static final int TILE = 64;

    public ScrollPanePaint() {
        JViewport viewport = new MyViewport();
        viewport.setView(new MyPanel());
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewport(viewport);
        this.add(scrollPane);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    private static class MyViewport extends JViewport {

        public MyViewport() {
            this.setOpaque(false);
            this.setPreferredSize(new Dimension(6 * TILE, 6 * TILE));
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(Color.blue);
            g.fillRect(TILE, TILE, 3 * TILE, 3 * TILE);
        }
    }

    private static class MyPanel extends JPanel {

        public MyPanel() {
            this.setOpaque(false);
            this.setPreferredSize(new Dimension(9 * TILE, 9 * TILE));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.lightGray);
            int w = this.getWidth() / TILE + 1;
            int h = this.getHeight() / TILE + 1;
            for (int row = 0; row < h; row++) {
                for (int col = 0; col < w; col++) {
                    if ((row + col) % 2 == 0) {
                        g.fillRect(col * TILE, row * TILE, TILE, TILE);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ScrollPanePaint();
            }
        });
    }
}

注:不透明なコンポーネント ( JTableなど) をスクロール ペインのビューとして設定すると、スクロール時に固定された青いボックスが移動するなど、奇妙な視覚的なバグが発生します。setOpaque(false)それを修正するには、ビュー コンポーネントで使用します。

于 2012-04-10T22:46:54.327 に答える