0

我试图在屏幕上出现一个圆圈,然后当用户单击圆圈内时,使他们能够在按下鼠标时拖动鼠标所在的圆圈。

这是我到目前为止的代码,拖动工作,但它允许用户在不按下圆圈内部的情况下拖动,就在按下屏幕上的任何位置时。

我希望我不会太混乱

这是我的代码,如果有人能告诉我需要更正的代码,它将为我节省更多时间。

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

public class DragCircle extends JFrame {
    private static final long serialVersionUID = 1L;

    public static int size = 400;

    public static int r = 10;

    private int x;

    private int y;

    private int cX;

    private int cY;

    private int dX;

    private int dY;

    private MouseHandler mh;

    boolean isCircleClicked = false;

    public static void main(String[] args) {
        DragCircle c1 = new DragCircle();
        c1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    public DragCircle() {

        super("Drag circle");

        cX = r + 100;
        cY = r + 100;

        mh = new MouseHandler();
        addMouseListener(mh);
        addMouseMotionListener(mh);

        setSize(size, size);
        setVisible(true);

    }

    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.RED);
        g.fillOval(cX, cY, r * 2, r * 2);

    }

    private class MouseHandler extends MouseAdapter implements
            MouseMotionListener {
        public void mousePressed(MouseEvent me)

        {

            if ((cX - me.getX()) * (cX - me.getX()) + (cY - me.getY())
                    * (cY - me.getY()) < r * r) {
                isCircleClicked = true;
            }
        }

        public void mouseDragged(MouseEvent me) {
            if (isCircleClicked) {

                x = me.getX() - dX;
                y = me.getY() - dY;
                cX = x + r;
                cY = y + r;
                repaint();
            }
        }

        public void mouseReleased(MouseEvent e) {
            isCircleClicked = false;
        }

    }

}
4

2 回答 2

2

你的一个问题是

public void mouseDragged(MouseEvent me) {
    if (isCircleClicked = true) {

您在这里所做的是设置isCircleClickedtrue每次拖动鼠标时。此语句还评估了true您可以在任何地方拖动并移动圆圈的原因。将此更改为

 if (isCircleClicked) {

你应该没问题。

下一个问题是您永远不会重置isCircleClickedfalse. 您应该按照以下方式执行此操作mouseReleased或更改您mousePressed的:

public void mousePressed(MouseEvent me) {
    isCircleClicked =
        (cX - me.getX()) * (cX - me.getX()) +
        (cY - me.getY)) * (cY - me.getY()) < r * r;
}

这将isCircleClicked相应地设置。

不过,还有一些事情要做。在当前表单中,您需要开始拖动到中心点的左上角,如下图所示:

+------+
| |
| .-|-。
| / | \
+--------+ |
    \ /
     '-_-'

这是因为您的绘图:fillOval获取椭圆的左上角以及边界矩形的宽度和高度。它不是中心点和各自的直径。因此,您需要按如下方式调整他的内容:

g.fillOval(cX - r, cY - r, r * 2, r * 2);

注意左侧和顶部的半径偏移。

此外,您的拖动代码需要更多的工作。您当前假设用户拖动圆的center。您需要做的是保存鼠标单击的坐标,然后根据鼠标相对于最后一点的移动来移动圆圈。当前,您正在相对于圆心移动,因此要使移动变得更好,您必须开始精确地在圆心处拖动。我会把它作为练习留给你:-)

此外,您的侦听器类已经从MouseAdapter继承,因此您不需要显式实现 MouseMotionListener,因为 MouseAdapter 已经实现了它。

于 2009-12-10T07:48:43.137 回答
0

你程序的结构是错误的。您永远不应该覆盖 JFrame 的 paint(...) 方法。这是一个古老的 AWT 技巧,不应该与 Swing 一起使用。

阅读 Swing 教程中关于自定义绘画的部分,以获取正确绘画方法的示例。基础是覆盖 JPanel 的 paintComponent(...) 方法,然后将面板添加到框架的内容窗格中。

关于您的问题,更好的解决方案是创建一个 Ellipse2D 对象来表示您的圆圈。那么自定义绘画就可以使用Graphics2D类的drawShape(...)方法了。然后在您的 MouseListener 代码中,您可以使用 Shape.contains(...) 方法来查看鼠标是否在圆上单击。

于 2009-12-10T07:37:18.447 回答