在 JPanel 中绘制的圆不会在 mouseClick 的位置绘制

Circle drawn in a JPanel does not get drawn at the position of mouseClick

我正在尝试创建一个允许用户在 JPanel 中移动圆圈的程序,但我遇到了一些问题。

我的程序:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.border.Border;
import javax.swing.BorderFactory;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.GridLayout;

public class SixthProgram
{
    public static void main(String[] args)
    {
        GUI prog=new GUI("SixthProgram");
        prog.setBounds(350,250,500,250);
        prog.setVisible(true);
    }
}

class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener
{
    JButton color1, color2, color3 ,color4 ,color5;
    JPanel mainPan, colorPan;
    Color color=Color.BLACK;

    int x=0,y=0;

    public GUI(String header)
    {
        super(header);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        maker();

        addMouseListener(this);
        addMouseMotionListener(this);

        add(mainPan , BorderLayout.CENTER);
        add(colorPan, BorderLayout.PAGE_END);
    }

    public void maker()
    {
        colorPan = new JPanel();

        Border raisedbevel = BorderFactory.createRaisedBevelBorder();
        Border loweredbevel = BorderFactory.createLoweredBevelBorder();
        Border compound = BorderFactory.createCompoundBorder(raisedbevel, loweredbevel);
        colorPan.setBorder(compound);

        colorPan.setLayout(new GridLayout(1, 0));

        mainPan = new JPanel(){
            @Override
            public void paintComponent(Graphics g)
            {
                //g.setColor(Color.WHITE);
                //g.fillRect(0,0,getWidth(),getHeight());
                super.paintComponent(g); //Do the same thing as above(Clear JPanel)

                g.setColor(color);
                g.fillOval(x,y,50,50);
            }
        };

        color1 = new JButton();
        color2 = new JButton();
        color3 = new JButton();
        color4 = new JButton();
        color5 = new JButton();

        color1.setBackground(Color.WHITE);
        color2.setBackground(Color.GREEN);
        color3.setBackground(Color.RED);
        color4.setBackground(Color.BLUE);
        color5.setBackground(Color.BLACK);

        color1.addActionListener(this);
        color2.addActionListener(this);
        color3.addActionListener(this);
        color4.addActionListener(this);
        color5.addActionListener(this);

        colorPan.add(color1);
        colorPan.add(color2);
        colorPan.add(color3);
        colorPan.add(color4);
        colorPan.add(color5);

        colorPan.setBackground(Color.GREEN);

    }

    public void mouseExited(MouseEvent e) //MouseListener overrided methods
    {
        System.out.println("Exit");
    }

    public void mouseEntered(MouseEvent e)
    {
        System.out.println("Enter");
    }

    public void mouseReleased(MouseEvent e)
    {
        System.out.println("Release");
    }

    public void mousePressed(MouseEvent e)
    {
        System.out.println("Press");    

        if((e.getX()+50 <= getWidth())  &&
           (e.getY()+50 <= (getHeight() - colorPan.getHeight()))) // Preventing out of bounds
        {
            x=e.getX();
            y=e.getY();
            repaint();
        }
    }

    public void mouseClicked(MouseEvent e) //Press+Release=Click
    {
        System.out.println("Click");
    }

    public void mouseDragged(MouseEvent e) //MouseMotionListener overrided methods
    {
        //System.out.println("Dragged to ("+ e.getX() +","+ e.getY() +")");

        if((e.getX()>=0 && e.getY()>=0) && 
           (e.getX()+50 <= getWidth())  &&
           (e.getY()+50 <= (getHeight() - colorPan.getHeight())) )
        {
            x=e.getX();
            y=e.getY();
            repaint();
        }
    }

    public void mouseMoved(MouseEvent e)
    {
        //System.out.println("Moved to ("+ e.getX() +","+ e.getY() +")");
    }

    public void actionPerformed(ActionEvent e)
    {
        JButton button = (JButton)e.getSource();
        color = button.getBackground();
        repaint();
    }

}

以上代码产生了预期的输出:

问题是:

  1. 当我拖动圆圈时,圆圈似乎没有画在鼠标所在的位置:

    在上面的截图中,我是拖动鼠标,但是圆圈似乎画在鼠标下方的位置。

  2. 在颜色选择器 JPanel(colorPan) 后面绘制圆圈(colorPan):

    我愿圆,不进colorPan的地盘

  3. 圆圈向右移动太远:

    您可以观察到圆圈的一部分在 JPanel 之外(mainPan)。

我很确定我的 mouseDragged 方法有问题:

public void mouseDragged(MouseEvent e)
{
    //System.out.println("Dragged to ("+ e.getX() +","+ e.getY() +")");

    if((e.getX()>=0 && e.getY()>=0) && 
       (e.getX()+50 <= getWidth())  &&
       (e.getY()+50 <= (getHeight() - colorPan.getHeight())) )
    {
        x=e.getX();
        y=e.getY();
        repaint();
    }
}

但我似乎找不到问题所在。谁能帮我解决这些问题?

您需要将 MouseListener/MouseMotionListener 添加到绘图面板,而不是接下来的 GUI :

  mainPan.addMouseListener(this);
  mainPan.addMouseMotionListener(this);

或者您可以使用 SwingUtilities.convertPoint(...) 方法将点从一个分量转换为另一个分量,如下所示:

Point convertPoint = SwingUtilities.convertPoint(GUI.this, e.getPoint(), mainPan);
x=convertPoint.x;
y=convertPoint.y;