8

簡単なペイントツールを作成しようとしています。mouseDragイベントは新しい楕円を作成し、私の原因となりJPanelますrepaint()

これは今のところうまく機能します。ただし、イベントを初めて発生させる前にボタン(またはその他のUIコンポーネント)をmouseDrag押すと、ボタンはパネルの左上隅に描画されます。

このテストアプリケーションにコードを分離しました。

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test extends JFrame
{
    public Test()
    {
        final JPanel paintPanel = new JPanel(){
            @Override
            protected void paintComponent(Graphics g)
            {
                Graphics2D g2d = (Graphics2D)g;
                g2d.setPaintMode();

                g2d.setStroke(new BasicStroke(1));
                g2d.fillRect(100, 100, 10, 10);
            }
        };

        paintPanel.setPreferredSize(new Dimension(300,300));
        paintPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                paintPanel.repaint();
            }
        });

        this.setLayout(new FlowLayout());

        this.add(paintPanel);
        this.add(new JButton("Dummy"));

        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String... args)
    {
        new Test();
    }
}

パネルをクリックする前のTestApp パネルをクリックした後のTestApp

メインアプリケーションで問題を「確認」するためのスクリーンショット

4

2 に答える 2

8

@MadProgrammerの回答に+1。

  • super.paintComponent(..)オーバーライドされた最初の呼び出しとして持つ必要がありますpaintComponent()
  • JFrame不必要に伸ばさないでください
  • EDTを介してSwingコンポーネントを作成および最小化します
  • setPrefferedSize()むしろオーバーライドを呼び出さないでくださいgetPrefferedSize()

これが私のアドバイスと@MadProgrammerを組み込んだ例です:

ここに画像の説明を入力してください

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    JFrame frame;

    public Test() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final PaintPanel paintPanel = new PaintPanel();

        paintPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                paintPanel.addRect(e.getX(), e.getY());
            }
        });

        frame.setLayout(new FlowLayout());

        frame.add(paintPanel);
        frame.add(new JButton("Dummy"));

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

    public static void main(String... args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }
}

class PaintPanel extends JPanel {

    public PaintPanel() {
        addRect(100, 100);
    }
    ArrayList<Rectangle> rects = new ArrayList<>();

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setPaintMode();

        for (Rectangle r : rects) {
            g2d.setStroke(new BasicStroke(1));
            g2d.fillRect(r.x, r.y, r.width, r.height);
        }
    }

    public void addRect(int x, int y) {
        rects.add(new Rectangle(x, y, 10, 10));
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }
}
于 2012-11-13T10:41:57.993 に答える
7

あなたは呼んでいないsuper.paintComponent

ペイントサイクルに使用されるグラフィックスコンテキストは、ペイントを開始するすべてのコンポーネント間で共有されます。つまり、ペイントする前にクリアすることに注意しないと、前にペイントされたものになってしまいます。

の仕事の1つは、paintComponentペイント用のグラフィックを準備することです。

于 2012-11-13T10:19:57.043 に答える