web-dev-qa-db-ja.com

ペイントブラシタイプのGUIでのpaintComponent()とPaint()およびJPanelとCanvas

thisthis 、および this の投稿から興味深いアイデアと批評を得ました(問題のGUIのコードについては、最後の投稿を参照してください)。それにもかかわらず、私はまだいくつかのことについてかなり混乱しています。主に、ユーザーが導入したグラフィックを表示する最も安価な方法は何ですか?

より具体的には、paintComponent()メソッドと一緒にMouseDragged()メソッドでこのクラスのオブジェクトを作成することにより、JPanelクラスのpaintComponent(getGraphics())メソッドを使用しました( _AuxClass2_および_AuxClass1_に応じて)。

どうやら、getGraphics()の代わりにpaintComponent()repaint()を使用するのは悪い考えです。メモリの使用と関係があるのではないかと思います。また、ユーザーがマウスをドラッグするたびに_AuxClass2_を呼び出すこともお勧めできません。

また、JPanelとCanvas(つまり、swingとawt)は少し混乱しています。何がいつ使用されますか?

私は回避策を見つけようとしましたが、特にgetGraphics()メソッドの場合は回避策を見つけていません。他にどのようにグラフィックスをパネルに追加できますか?

15
Alex

私は回避策を見つけようとしましたが、特にgetGraphics()メソッドの場合は回避策を見つけていません。グラフィックをパネルに追加するにはどうすればよいですか。

何を変数としてペイントする必要があるかを覚えて、それをpaintComponent()で使用します。たとえば、あなたが他の質問でやろうとしているように見えることは次のようになります:

import Java.awt.*;
import Java.awt.event.*;
import javax.swing.*;

public class PaintRectangle extends JPanel {

    private Point mouseLocation;

    public PaintRectangle() {
        setPreferredSize(new Dimension(500, 500));

        MouseAdapter listener = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                updateMouseRectangle(e);
            }

            private void updateMouseRectangle(MouseEvent e) {
                mouseLocation = e.getPoint();
                repaint();
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                updateMouseRectangle(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                mouseLocation = null;
                repaint();
            }
        };
        addMouseListener(listener);
        addMouseMotionListener(listener);
    }

    private Rectangle getRectangle() {
        if(mouseLocation != null) {
            return new Rectangle(mouseLocation.x - 5, mouseLocation.y - 5, 10, 10);
        }
        else {
            return null;
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Rectangle rectangle = getRectangle();
        if(rectangle != null) {
            Graphics2D gg = (Graphics2D) g;
            gg.setColor(Color.BLUE);
            gg.fill(rectangle);
            gg.setColor(Color.BLACK);
            gg.draw(rectangle);
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new PaintRectangle());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

参照 http://docs.Oracle.com/javase/tutorial/uiswing/painting/

7
Walter Laan

重いvs軽量

基本的に、重いコンポーネントは独自のネイティブピアにリンクされ、軽量コンポーネントは共通のネイティブピアを共有します。

一般に、Zオーダーに問題があり、私の経験では(現在はより良いはずですが)塗装の問題が発生する可能性があるため、重量コンポーネントと軽量コンポーネントを混合することはお勧めできません。

これがCanvasクラスの使用を思いとどまらせた理由です。おそらく、軽量コンポーネントに配置しようとしていたからでしょう...

コントロールの幻想

Swing API の初心者にとっての最大の問題の1つは、描画プロセスを何らかの方法で制御できるという幻想ですが、そうではありません。受け入れるだけの方が簡単です。

あなたができる最善のことは、再描画マネージャができるだけ早く更新を実行するように要求することです。

また、getGraphicsを呼び出してもnull以外の値が返されるとは限りません。

正しい順序

PaintpaintComponent

ここでの問題はPaintがいくつかの重要な仕事をしていることです。paintComponentの呼び出しはその1つにすぎません。

Swingでは、カスタムペイントを実行する場合は常にpaintComponentを使用することを強くお勧めします。これは通常、コンポーネントの最下位レベルであり、子コンポーネントがペイントされる前に呼び出されます。

Paintをオーバーライドし、Graphicssuper.Paintの呼び出し後にペイントすると、すべての上にペイントされることになりますが、これは必ずしも望ましい結果とは限りません

たとえあったとしても、子コンポーネントは親コンテナとは独立してペイントできるため、追加したペイントエフェクトの上に「ペイント」できます。

役立つリンク

別れの考え

ネイティブピアに接続されているコンポーネントに実際に追加されたコンポーネントのみが、Paintメソッドが呼び出されます。したがって、まだコンテナに追加されていないコンポーネントにペイントしようとしても、意味がありません...

20
MadProgrammer

..paintbrush-type GUI ..

BufferedImageを描画面として使用します。 JLabelに表示します。 JScrollPane内のパネルの中央にラベルを配置します。

必要に応じてbufferedImage.getGraphics()を呼び出しますが、完了したらdispose()を忘れずにlabel.repaint()を呼び出します。

全体でSwingコンポーネントを使用し、何もオーバーライドしないでください。

これが 画像をペイントサーフェスとして使用する例 です。

そして これはより良いものです

screen-shotの方が優れていたとは言いませんでした。コードの方が優れています。 ;)

9
Andrew Thompson