Java 绘制以鼠标单击为中心的圆时出现问题

Java 绘制以鼠标单击为中心的圆时出现问题,java,swing,draw,Java,Swing,Draw,我正在尝试编写一个程序,在鼠标点击时画一个圆圈,圆圈以鼠标点击的坐标为中心。我的圆圈是50乘50。在我的鼠标侦听器类中,我将偏移x-25和y-25,但是,圆圈不会显示在单击的中心。它显示在单击按钮的稍下方 public class CircleDraw extends JPanel private JFrame frame; private JPanel P1; private int circlecount; private int x, y; MouseClicks minney;

我正在尝试编写一个程序,在鼠标点击时画一个圆圈,圆圈以鼠标点击的坐标为中心。我的圆圈是50乘50。在我的鼠标侦听器类中,我将偏移x-25和y-25,但是,圆圈不会显示在单击的中心。它显示在单击按钮的稍下方

public class CircleDraw extends JPanel 


private JFrame frame;
private JPanel P1;

private int circlecount;
private int x, y;
MouseClicks minney;
ArrayList<Circle> circles = new ArrayList<Circle>();

public CircleDraw()
{
    frame = new JFrame("CircleDraw");
    frame.setSize(800,800);
    minney = new MouseClicks();

    //circles.add(new Circle(x,y));//This may be the original circle being added
    this.setBackground(Color.BLACK);
    this.setPreferredSize(new Dimension(800,800));
    frame.add(this);

    frame.pack();
    frame.setVisible(true);
    frame.addMouseListener(minney);

} 

public class Circle
{
    int x, y;

    public Circle(int x, int y) 
    {
        this.x = x; this.y = y;

    }

    public void draw(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.GREEN);
        g2d.fillOval(x,y,50,50);
    }

}
@Override
protected void paintComponent(Graphics g)
{

    {
        super.paintComponent(g);
        for (Circle c : circles)
            c.draw(g);
    }
}

public class MouseClicks implements MouseListener
{
    int x, y, b;

    public void mouseClicked(MouseEvent m) 
    {
        int x = m.getX(), y = m.getY();  b = m.getButton();
        this.x = x; 
        this.y = y;


        {
            circles.add(new Circle(x-25, y-25)); 
            CircleDraw.this.repaint();


        }

    }

    public void mouseEntered(MouseEvent m) {}

    public void mouseExited(MouseEvent m) {}

    public void mousePressed(MouseEvent m) {}

    public void mouseReleased(MouseEvent m) {}
}
}
公共类CircleDraw扩展了JPanel
私有JFrame;
私人JPanel P1;
私人国际循环计数;
私有整数x,y;
米尼;
ArrayList圆圈=新的ArrayList();
公共电路图()
{
框架=新的JFrame(“CircleDraw”);
框架设置尺寸(800800);
minney=新鼠标点击();
//圆。添加(新圆(x,y));//这可能是要添加的原始圆
这个.背景(颜色.黑色);
此.setPreferredSize(新尺寸(800800));
框架。添加(此);
frame.pack();
frame.setVisible(true);
帧。addMouseListener(米尼);
} 
公共阶级圈子
{
int x,y;
公众圈(整数x,整数y)
{
这个.x=x;这个.y=y;
}
公共空间绘制(图g)
{
Graphics2D g2d=(Graphics2D)g;
g2d.setColor(Color.GREEN);
g2d.椭圆形(x,y,50,50);
}
}
@凌驾
受保护组件(图形g)
{
{
超级组件(g);
用于(圆c:圆)
c、 抽签(g);
}
}
公共类MouseClicks实现MouseListener
{
int x,y,b;
公共无效mouseClicked(MouseEvent m)
{
int x=m.getX(),y=m.getY();b=m.getButton();
这个.x=x;
这个。y=y;
{
圆。添加(新的圆(x-25,y-25));
CircleDraw.this.repaint();
}
}
公共无效mouseenterned(MouseEvent m){}
public void mouseExited(MouseEvent m){}
public void mousePressed(MouseEvent m){}
公共无效MouseEvent m{}
}
}

您将鼠标侦听器添加到错误的组件。在这里:

frame.addMouseListener(minney);
您正在将其添加到JFrame,当您需要将其添加到实际进行绘图的组件时,JFrame会将鼠标坐标向下平移JFrame标题栏的距离,
this
,以便鼠标按下坐标与绘图坐标匹配:

addMouseListener(minney);
或者明确地

this.addMouseListener(minney);
例如,与您的代码类似的可拖动圆:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class CircleDraw2 extends JPanel {
    private static final int CIRCLE_RADIUS = 25;
    private static final Color BACKGROUND = Color.BLACK;
    private int prefW;
    private int prefH;
    List<Circle2> circles = new ArrayList<>();

    public CircleDraw2(int prefW, int prefH) {
        this.prefW = prefW;
        this.prefH = prefH;
        setBackground(BACKGROUND);
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(prefW, prefH);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        for (Circle2 circle : circles) {
            circle.draw(g2);
        }
    }

    private class MyMouse extends MouseAdapter {
        private Point p0 = null;
        private Circle2 selection = null;

        @Override
        public void mousePressed(MouseEvent e) {
            for (int i = circles.size() - 1; i >= 0; i--) {
                if (circles.get(i).contains(e.getPoint())) {
                    // if mouse clicks on a circle that already exists
                    p0 = e.getPoint(); 
                    selection = circles.get(i); // select that pressed circle

                    // move it to the top
                    circles.remove(selection);
                    circles.add(selection);
                    repaint();
                    return;
                }
            }

            // no circle selected, so create a new one
            int centerX = e.getX();
            int centerY = e.getY();
            Color c = createRandomColor();
            selection = new Circle2(centerX, centerY, CIRCLE_RADIUS, c);
            circles.add(selection);
            p0 = e.getPoint();
            repaint();
        }

        private Color createRandomColor() {
            double minRand = 0.7; // min saturation and brightness
            float hue = (float) Math.random();
            float saturation = (float)((1 - minRand) * Math.random() + minRand);
            float brightness = (float)((1 - minRand) * Math.random() + minRand);
            Color c = Color.getHSBColor(hue, saturation, brightness);
            return c;
        }

        private void drag(Point p1) {
            if (p0 == null) {
                return;
            }
            selection.move(p0, p1);
            p0 = p1;
            repaint();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            drag(e.getPoint());
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            drag(e.getPoint());
            p0 = null;
            selection = null;
        }
    }

    private static void createAndShowGui() {
        int width = 800;
        int height = width;
        CircleDraw2 mainPanel = new CircleDraw2(width, height);

        JFrame frame = new JFrame("CircleDraw2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

为什么您
扩展JPanel
并拥有
私有JPanel P1?谢谢-这是个明显的错误。我感谢你的帮助!
class Circle2 {
    private Color color;
    private Path2D path; // easily moveable with affine transform

    public Circle2(int centerX, int centerY, int radius, Color color) {
        this.color = color;
        double x = centerX - radius;
        double y = centerY - radius;
        double w = 2 * radius;
        double h = w;
        Ellipse2D e2d = new Ellipse2D.Double(x, y, w, h);
        path = new Path2D.Double(e2d);
    }    

    public void move(Point p0, Point p1) {
        // get the distance or "delta" of the move
        int deltaX = p1.x - p0.x;
        int deltaY = p1.y - p0.y;

        // move the circle delta amount
        path.transform(AffineTransform.getTranslateInstance(deltaX, deltaY));
    }

    public void draw(Graphics2D g2) {
        g2.setColor(color);
        g2.fill(path);
        g2.setColor(Color.BLACK);
        g2.draw(path);
    }

    public int getCenterX() {
        return (int) path.getBounds().getCenterX();
    }

    public int getCenterY() {
        return (int) path.getBounds().getCenterY();
    }

    public int getRadius() {
        return (int) path.getBounds().getWidth() / 2;
    }

    public Color getColor() {
        return color;
    }

    public Shape getEllipse() {
        return path;
    }  

    public boolean contains(Point p) {
        return path.contains(p);
    }

}