我想在屏幕上显示一个圆圈,然后当用户点击圆圈内侧时,启用它们可以拖动鼠标按下时所在的圆圈。
这是我到目前为止的代码,拖动工作,但它允许用户在没有按下圆圈内部的情况下拖动,就在按下屏幕上的任何位置时。
我希望我不会太困惑
这是我的代码,如果有人可以告诉我需要更正的代码,它将为我节省更多时间。
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;
}
}
}
答案 0 :(得分:2)
你的一个问题是
public void mouseDragged(MouseEvent me) {
if (isCircleClicked = true) {
您在这里做的是每次拖动鼠标时将isCircleClicked
设置为true
。此语句也会评估为true
,这就是您可以拖动任何位置并移动圆圈的原因。将其更改为
if (isCircleClicked) {
你应该没事。
下一个问题是,您永远不会将isCircleClicked
重置为false
。您应该在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);
请注意半径到左侧和顶部的偏移量。
此外,您的拖动代码还需要更多工作。您目前假设用户拖动了圈子的中心。您需要做的是保存鼠标单击的坐标,然后根据鼠标相对于最后一点的移动移动圆。目前你正在相对于圆的中心移动,所以为了让运动变得更好,你必须开始正好在圆的中心拖动。我会把它作为练习留给你: - )
此外,您的侦听器类已经从MouseAdapter继承,因此您不需要显式实现MouseMotionListener,因为MouseAdapter已经实现了它。
答案 1 :(得分:0)
你的程序结构错了。您永远不应该覆盖JFrame的paint(...)方法。这是一个古老的AWT技巧,不应该与Swing一起使用。
阅读Custom Painting上Swing教程中的部分,了解正确绘画方法的示例。基础是覆盖JPanel的paintComponent(...)方法,然后将面板添加到框架的内容窗格中。
关于你的问题,更好的解决方案是创建一个Elllipse2D对象来表示你的圈子。然后自定义绘画可以使用Graphics2D类的drawShape(...)方法。然后在您的MouseListener代码中,您可以使用Shape.contains(...)方法查看是否在圆圈上单击了鼠标。