感知悬停在JPanel中Path2D圆的外边缘上

时间:2014-10-19 23:08:06

标签: java swing shapes

所以,我有一个程序将Path2D圈子绘制到JPanel上。我想要做的是在用户点击并拖动圆圈的右下角时调整圆圈的大小。所以,我想要的是检测它们何时位于圆圈的右下角外边缘,而不是圆圈周围边界的右下角。基本上,我需要弄清楚如何做这样的事情:

enter image description here

我知道如何使用getBounds()对矩形执行此操作,但是当您在圆上使用getBounds()时,它将返回围绕圆的方形而不是实际圆的边界。关于如何让这个工作的任何想法?谢谢!

这是我的程序的缩短的,可运行的版本:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Editor {

    public static void main(String[] args) {

        JFrame frame = new UMLWindow();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(30, 30, 1000, 700);
        frame.getContentPane().setBackground(Color.white);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class UMLWindow extends JFrame {
    Shapes shapeList = new Shapes();
    Panel panel;

    private static final long serialVersionUID = 1L;

    public UMLWindow() {
        addMenus();
        panel = new Panel();
    }

    public void addMenus() {

        getContentPane().add(shapeList);

        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        shapeList.addCircle(100, 100);
    }
}

// Shapes class, used to draw the shapes on the panel
// as well as implements the MouseListener for dragging
class Shapes extends JPanel {
    private static final long serialVersionUID = 1L;

    private List<Path2D> shapes = new ArrayList<Path2D>();
    int currentIndex;

    public Shapes() {
        MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
        addMouseListener(myMouseAdapter);
        addMouseMotionListener(myMouseAdapter);
    }

    public void addCircle(int width, int height) {
        Path2D circ = new Path2D.Double();
        circ.append(new Ellipse2D.Double(442, 269, width, height), true);
        shapes.add(circ);
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(2));
        for (Path2D shape : shapes) {
            g2.draw(shape);
        }
    }

    class MyMouseAdapter extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {

        }

        @Override
        public void mouseDragged(MouseEvent e) {
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }
    }
}

2 个答案:

答案 0 :(得分:2)

不确定这是否有效,但您可以尝试以下方法:

  1. 创建一个比原始形状小几个像素的形状圆
  2. 创建一个比原始形状大几个像素的形状圆
  3. 使用较大的Shape
  4. 创建Area对象
  5. 使用较小的Shape创建Area对象,并从较大的Area
  6. 中减去此Area
  7. 使用contains(...)方法确定鼠标点是否在此区域内。

答案 1 :(得分:2)

你想要刷新你的触发(或谷歌搜索,就像我做的那样;))。基本概念“相对”容易,但我为我的所有工作创造了一个很好的方法......

这种方法......

public Point2D getPointOnEdge(float angel, Rectangle bounds) {

    float radius = Math.max(bounds.width, bounds.height) / 2;

    float x = radius;
    float y = radius;

    double rads = Math.toRadians((angel + 90));

    // Calculate the outter point of the line
    float xPosy = (float) (x + Math.cos(rads) * radius);
    float yPosy = (float) (y + Math.sin(rads) * radius);

    return new Point2D.Float(xPosy + bounds.x, yPosy + bounds.y);

}

将计算给定角度出现在圆圈上的x / y点,请记住,这只适用于圆圈!

然后我使用另一种方法...

public Rectangle2D getActiveBounds(float angel, Rectangle bounds) {

    Point2D p = getPointOnEdge(angel, bounds);

    return new Rectangle2D.Double(p.getX() - 4, p.getY() - 4, 8, 8);

}

要计算我认为是底部/右侧区域的“鼠标区域”,导致难以找到单个像素,只需使用Rectangle#contains,将其传递给当前鼠标位置...... < / p>

Mouse Hover

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Editor {

    public static void main(String[] args) {
        new Editor();
    }

    public Editor() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new UMLWindow();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setBounds(30, 30, 1000, 700);
                frame.getContentPane().setBackground(Color.white);
                frame.setVisible(true);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class UMLWindow extends JFrame {

        Shapes shapeList = new Shapes();
        Panel panel;

        private static final long serialVersionUID = 1L;

        public UMLWindow() {
            addMenus();
            panel = new Panel();
        }

        public void addMenus() {

            getContentPane().add(shapeList);

            setSize(300, 200);
            setLocationRelativeTo(null);
            setDefaultCloseOperation(EXIT_ON_CLOSE);

            shapeList.addCircle(100, 100);
        }
    }

// Shapes class, used to draw the shapes on the panel
// as well as implements the MouseListener for dragging
    public static class Shapes extends JPanel {

        private static final long serialVersionUID = 1L;

        private List<Path2D> shapes = new ArrayList<Path2D>();
        int currentIndex;

        private Point mousePoint;

        public Shapes() {
            MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
            addMouseListener(myMouseAdapter);
            addMouseMotionListener(myMouseAdapter);
        }

        public void addCircle(int width, int height) {
            Path2D circ = new Path2D.Double();
            circ.append(new Ellipse2D.Double(442, 269, width, height), true);
            shapes.add(circ);
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2 = (Graphics2D) g;
            g2.setStroke(new BasicStroke(2));
            for (Path2D shape : shapes) {
                g2.setColor(Color.BLACK);
                g2.draw(shape);

                g2.setColor(Color.RED);
                Rectangle2D bottomRight = getActiveBounds(-45, shape.getBounds());

                g2.draw(bottomRight);
                if (mousePoint != null) {

                    if (bottomRight.contains(mousePoint)) {
                        g2.fill(bottomRight);
                    }

                }

            }
        }

        public Rectangle2D getActiveBounds(float angel, Rectangle bounds) {

            Point2D p = getPointOnEdge(angel, bounds);

            return new Rectangle2D.Double(p.getX() - 4, p.getY() - 4, 8, 8);

        }

        public Point2D getPointOnEdge(float angel, Rectangle bounds) {

            float radius = Math.max(bounds.width, bounds.height) / 2;

            float x = radius;
            float y = radius;

            double rads = Math.toRadians((angel + 90));

            // Calculate the outter point of the line
            float xPosy = (float) (x + Math.cos(rads) * radius);
            float yPosy = (float) (y + Math.sin(rads) * radius);

            return new Point2D.Float(xPosy + bounds.x, yPosy + bounds.y);

        }

        class MyMouseAdapter extends MouseAdapter {

            @Override
            public void mouseMoved(MouseEvent e) {
                mousePoint = e.getPoint();
                repaint();
            }

        }
    }

}

这个例子完成了paint方法中的所有工作,因为我想看到“效果区域”,你可以轻松地使用相同的逻辑来改变MouseMoitionListener

中的鼠标光标