当前位置: 首页 > 面试题库 >

通过单击并拖动其外部边缘来调整Path2D圆的大小

简景焕
2023-03-14
问题内容

因此,当我在JPanel上单击并拖动Path2D圆时,它正在调整大小。该
问题是,当我最初点击和拖动它,圆跳转到一个
更小的尺寸,但是当你单击并拖动,然后正确地调整大小。
演示的最简单方法是运行下面的可运行代码。

我知道我需要修复此代码:

@Override
public void mouseDragged(MouseEvent e) {
    int mouseX = e.getX();
    int mouseY = e.getY();
    if (resizing) {
        System.out.println("resizing");
        Rectangle bounds = shapes.get(currentIndex).getBounds();
        int shapeX = bounds.x;
        int shapeY = bounds.y;
        shapes.get(currentIndex).reset();
        shapes.get(currentIndex).append(
                new Ellipse2D.Double(shapeX, shapeY, mouseX
                        - shapeX, mouseX - shapeX), true);
        repaint();
    }
}

我不确定如何。我单击圆的外边缘,然后将圆的边界的长度和宽度设置为新鼠标点所在的位置…但是我需要做的是
圆的坐标的外边缘新的鼠标点。关于如何计算正确点的任何想法?

完整代码

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
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);
            }
        }

        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 {
            Boolean hovering = false;
            Boolean resizing = true;

            @Override
            public void mouseMoved(MouseEvent e) {
                mousePoint = e.getPoint();
                for (int i = 0; i < shapes.size(); i++) {
                    Path2D shape = shapes.get(i);
                    Rectangle2D bottomRight = getActiveBounds(-45,
                            shape.getBounds());

                    if (mousePoint != null) {

                        if (bottomRight.contains(mousePoint)) {
                            Cursor cursor = Cursor
                                    .getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
                            setCursor(cursor);
                            hovering = true;
                        } else {
                            Cursor cursor = Cursor
                                    .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
                            setCursor(cursor);
                            hovering = false;
                        }
                    }
                }

                repaint();
            }

            @Override
            public void mousePressed(MouseEvent e) {
                if (hovering) {
                    resizing = true;
                    System.out.println("Starting to resize");
                }
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                int mouseX = e.getX();
                int mouseY = e.getY();
                if (resizing) {
                    System.out.println("resizing");
                    Rectangle bounds = shapes.get(currentIndex).getBounds();
                    int shapeX = bounds.x;
                    int shapeY = bounds.y;
                    shapes.get(currentIndex).reset();
                    shapes.get(currentIndex).append(
                            new Ellipse2D.Double(shapeX, shapeY, mouseX
                                    - shapeX, mouseX - shapeX), true);
                    repaint();
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (resizing) {
                    System.out.println("Done resizing");
                    resizing = false;
                }
            }

        }
    }

}

问题答案:

您需要知道两件事,您需要知道
鼠标被按下的原始点和形状的原始边界

private Point clickPoint;
private Rectangle originalBounds;
//...
@Override
public void mousePressed(MouseEvent e) {
    if (hovering) {
        resizing = true;
        System.out.println("Starting to resize");
        clickPoint = e.getPoint();
        originalBounds = new Rectangle(shapes.get(currentIndex).getBounds());
    }
}

With this information you can calculate the delta between the original click
point and the drag point, armed with this information, you can modify the the
shape by adding the difference to the originalBounse

@Override
public void mouseDragged(MouseEvent e) {
    if (resizing && clickPoint != null) {

        int mouseX = e.getX();
        int mouseY = e.getY();

        int xDelta = mouseX - clickPoint.x;
        int yDelta = mouseY - clickPoint.y;

        int delta = Math.max(xDelta, yDelta);

        Rectangle bounds = shapes.get(currentIndex).getBounds();
        int shapeX = bounds.x;
        int shapeY = bounds.y;

        int shapeWidth = originalBounds.width + delta;
        int shapeHeight = originalBounds.height + delta;

        if (shapeWidth < 0) {
            shapeWidth *= -1;
            shapeX = originalBounds.x - shapeWidth;
        }
        if (shapeHeight < 0) {
            shapeHeight *= -1;
            shapeY = originalBounds.y - shapeHeight;
        }

        System.out.printf("%d %dx%dx%dx%d%n", delta, shapeX, shapeY, shapeWidth, shapeHeight);

        shapes.get(currentIndex).reset();
        shapes.get(currentIndex).append(
                        new Ellipse2D.Double(shapeX, shapeY, shapeWidth, shapeHeight), true);
        repaint();
    }
}

Just don’t forget to reset the clickPoint and originalBounds when the user
releases the button ;)

Resize

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
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);
            }
        }

        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 {

            Boolean hovering = false;
            Boolean resizing = true;

            private Point clickPoint;
            private Rectangle originalBounds;

            @Override
            public void mouseMoved(MouseEvent e) {
                mousePoint = e.getPoint();
                for (int i = 0; i < shapes.size(); i++) {
                    Path2D shape = shapes.get(i);
                    Rectangle2D bottomRight = getActiveBounds(-45,
                                    shape.getBounds());

                    if (mousePoint != null) {

                        if (bottomRight.contains(mousePoint)) {
                            Cursor cursor = Cursor
                                            .getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
                            setCursor(cursor);
                            hovering = true;
                        } else {
                            Cursor cursor = Cursor
                                            .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
                            setCursor(cursor);
                            hovering = false;
                        }
                    }
                }

                repaint();
            }

            @Override
            public void mousePressed(MouseEvent e) {
                if (hovering) {
                    resizing = true;
                    System.out.println("Starting to resize");
                    clickPoint = e.getPoint();
                    originalBounds = new Rectangle(shapes.get(currentIndex).getBounds());
                }
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (resizing && clickPoint != null) {

                    int mouseX = e.getX();
                    int mouseY = e.getY();

                    int xDelta = mouseX - clickPoint.x;
                    int yDelta = mouseY - clickPoint.y;

                    int delta = Math.max(xDelta, yDelta);

                    Rectangle bounds = shapes.get(currentIndex).getBounds();
                    int shapeX = bounds.x;
                    int shapeY = bounds.y;

                    int shapeWidth = originalBounds.width + delta;
                    int shapeHeight = originalBounds.height + delta;

                    if (shapeWidth < 0) {
                        shapeWidth *= -1;
                        shapeX = originalBounds.x - shapeWidth;
                    }
                    if (shapeHeight < 0) {
                        shapeHeight *= -1;
                        shapeY = originalBounds.y - shapeHeight;
                    }

                    System.out.printf("%d %dx%dx%dx%d%n", delta, shapeX, shapeY, shapeWidth, shapeHeight);

                    shapes.get(currentIndex).reset();
                    shapes.get(currentIndex).append(
                                    new Ellipse2D.Double(shapeX, shapeY, shapeWidth, shapeHeight), true);
                    repaint();
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (resizing) {
                    System.out.println("Done resizing");
                    resizing = false;
                    clickPoint = null;
                    originalBounds = null;
                }
            }

        }
    }

}


 类似资料:
  • 所以,我有一个程序可以在JPanel上绘制Path2D圆。我试图做的是当用户点击并拖动圆圈右下角时调整圆圈的大小。所以,我想要检测的是它们何时在圆的右下角外边缘,而不是圆周围边界的右下角。基本上,我需要弄清楚如何做这样的事情: 我知道如何使用getBounds()来处理矩形,但是当您在圆上使用getBounds()时,它将返回圆周围的正方形,而不是实际圆的边界。有什么办法可以让它工作吗?谢谢 这是

  • 我正在使用SWT,我希望能够通过拖动它的角来调整复合的大小,就像您可以调整shell的大小一样。我肯定有人已经实施了一个很好的解决方案。多谢了。

  • 我试图在JavaFX中执行以下操作。我正在用画布在屏幕上画东西,我希望发生以下事情: 当我点击画布表面时(比如快速按下并释放):有些事情发生了 当我在画布表面拖动时(如按住并移动,然后释放):会发生其他事情 但是如果我拖动,我希望它排除单击操作,所以如果我拖动,如果我单击,会发生什么事情,而不应该发生。不幸的是,当我释放鼠标时,释放和单击事件都会启动,即使我拖动鼠标。

  • 我的场景中有一个对象。我希望能够调整窗口的大小,并与它一起调整窗格的大小。我还想在窗格旁边放置一个。 到目前为止,我已经成功地生成了一个完全可调整大小的或一个,其中包含和对象,但当我调整窗口大小时,窗格不会随之调整大小。 以下是带有锚烷的FXML: 只有的版本基本上就是版本中使用的代码,但具有和属性。 如何制作一个场景,使其具有可调整大小的和?

  • 问题内容: 我想通过单击其中的关闭链接 或 单击该div外部的任何位置来隐藏div。 我正在尝试下面的代码,它可以通过单击正确的关闭链接来打开和关闭div,但是如果我在单击div以外的任何位置来关闭它时遇到问题。 问题答案: 另一种使您的jsfiddle减少错误的方法(需要双击打开)。 这不会在主体级别使用任何委托事件 设置为DIV .popup(以及样式CSS )

  • 问题内容: 我试图通过拖放在由PyQt5创建的GUI上绘制一个矩形。我设法做到了,但是释放鼠标左键时就绘制了矩形。 我想做的就是这个链接: 当按下鼠标左键时,开始绘制矩形。 拖动时,通过鼠标移动调整矩形形状。 释放鼠标左键时,确定矩形形状。 我该如何实施?提前致谢。 这是我的代码。 问题答案: 您不必使用该函数,但是每次移动鼠标时都会调用该函数,并且我已经修改了代码以使其更简单。