首页 > 解决方案 > 尝试使用 MouseListener 和 MouseMotionListener 创建圈子——我做错了什么?

问题描述

我正在尝试使用 JComponent 在 JFrame 中创建 Circles。这是我想要实现的目标:我正在努力实现的目标。

这是我的代码发生的事情:在此处输入图像描述

我不知道是什么导致了这个问题。这是我的代码:

CircleViewer.java

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

public class CircleViewer
{
    public static void main(String[] args)
    {
        final CirclePanel panel = new CirclePanel();
        class MousePressListener implements MouseListener, MouseMotionListener
        {
            public void mouseClicked(MouseEvent event) { }
            public void mouseEntered(MouseEvent event) { }
            public void mouseExited(MouseEvent event) { }
            public void mouseWheelMoved(MouseWheelEvent event) { }
            public void mouseMoved(MouseEvent event) { }

            public void mousePressed(MouseEvent event)
            {
                var x = event.getX();
                var y = event.getY();
                panel.addCircle(x, y);
            }

            public void mouseDragged(MouseEvent event)
            {
                var x = event.getX();
                var y = event.getY();
                panel.moveTo(x, y);
            }

            public void mouseReleased(MouseEvent event)
            {
                panel.finalMove();
            }
        }
        MousePressListener listener = new MousePressListener();
        panel.addMouseListener(listener);
        panel.addMouseMotionListener(listener);

        JFrame frame = new JFrame("Circle Shapes");

        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(panel);
        frame.setVisible(true); 
    }
    private static final int FRAME_WIDTH = 700;
    private static final int FRAME_HEIGHT = 500;
}

CirclePanel.java

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.util.ArrayList;
import java.awt.Color;
import java.lang.Math;
import java.awt.BasicStroke;
import java.awt.Stroke;

public class CirclePanel extends JComponent
{
    private int lineX;
    private int lineY;
    private boolean isDraged;
    private ArrayList<Circle> circleList;
    private BasicStroke dashLine;
    public CirclePanel()
    {
        this.circleList = new ArrayList<Circle>();
        this.isDraged = false;
        this.lineX = 0;
        this.lineY = 0;
        this.dashLine = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{6}, 0);
    }

    public void addCircle(int x, int y)
    {
        lineX = x;
        lineY = y;
        isDraged = true;
        circleList.add(new Circle(x, y, 0, Color.RED));
        repaint();
    }

    public void moveTo(int x, int y)
    {
        var circleTemp = circleList.get(circleList.size() - 1);
        isDraged = true;
        var tempR = (int)Math.sqrt(Math.pow(x - circleTemp.get(0), 2) + Math.pow(y - circleTemp.get(1), 2));
        System.out.println(tempR);
        var tempX = circleTemp.get(0) - (tempR / 2);
        var tempY = circleTemp.get(1) - (tempR / 2);

        circleList.get(circleList.size() - 1).setCords(tempX, tempY, tempR);
        lineX = x;
        lineY = y;
        repaint();
    }
    public void finalMove()
    {
        isDraged = false;
        circleList.get(circleList.size() - 1).setColor(Color.BLUE);
        repaint();
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        Stroke defaultStroke;
        defaultStroke = g2.getStroke();
        if (!circleList.isEmpty())
        {
            if (isDraged)
            {
                g2.setColor(Color.RED);
                g2.setStroke(dashLine);
                g2.drawLine(circleList.get(circleList.size() - 1).get(0), circleList.get(circleList.size() - 1).get(1), lineX, lineY);
            }
            for (Circle circle : circleList) 
            {
                g2.setStroke(defaultStroke);
                circle.draw(g2);
                isDraged = false; //this is prob reduntant
            }
        }
    }
}

最后,Circle.java

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

public class Circle
{
    private int x;
    private int y;
    private int radius;
    private Color color;

    public Circle(int x, int y, int radius, Color color)
    {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.color = color;
    }

    public int get(int option)
    {
        switch (option)
        {
            case 0:
                return this.x;
            case 1:
                return this.y;
            case 2:
                return this.radius;
        }
        return 0;
    }

    public Color get()
    {
        return this.color;
    }

    public void setCords(int x, int y, int r)
    {
        this.x = x;
        this.y = y;
        this.radius = r;
    }
    public void set(int option, int value)
    {
        switch (option)
        {
            case 0: //set x
                this.x = value;
                break;
            case 1:
                this.y = value;
                break;
            case 2:
                radius = value;
                break;
        }
    }

    public void setColor(Color color)
    {
        this.color = color;
    }

    public void draw(Graphics2D g2)
    {
        g2.setColor(color);
        g2.draw(new Ellipse2D.Double(x, y, radius, radius));
    }
}

标签: java

解决方案


我没有在你的代码中找到具体的问题,而是决定做一个更干净的实现。使用这个圈子类

class Circle {
    final int x;
    final int y;
    int radius;

    public Circle(int x, int y, int radius) {
        this.x = x;
        this.y = y;
        this.radius = radius;
    }
}

您可以像这样实现 CirclePanel:

public class CirclePanel extends JPanel {
    private static final Stroke DASHED = new BasicStroke(1,
            BasicStroke.CAP_BUTT, 
            BasicStroke.JOIN_BEVEL, 
            0, new float[]{6}, 0);

    public Color oldCircleColor = Color.BLUE;
    public Color newCircleColor = Color.RED;
    public Color backgroundColor = Color.LIGHT_GRAY;

    private final List<Circle> oldCircles = new ArrayList<>();
    private Circle newCircle = null;
    private int mouseX = 0;
    private int mouseY = 0;

    private class MouseHelper implements MouseListener, MouseMotionListener {
        @Override public void mouseMoved(MouseEvent e) {}
        @Override public void mouseClicked(MouseEvent e) {}
        @Override public void mousePressed(MouseEvent e) {}
        @Override public void mouseEntered(MouseEvent e) {}
        @Override public void mouseExited(MouseEvent e) {}

        @Override
        public void mouseDragged(MouseEvent e) {
            mouseX = e.getX();
            mouseY = e.getY();
            if (newCircle == null) {
                newCircle = new Circle(mouseX, mouseY, 0);
            } else {
                int dX = newCircle.x - mouseX;
                int dY = newCircle.y - mouseY;
                newCircle.radius = (int) Math.sqrt(dX*dX + dY*dY);
            }
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (newCircle != null) {
                oldCircles.add(newCircle);
                newCircle = null;
                repaint();
            }
        }

    }

    public CirclePanel() {
        MouseHelper helper = new MouseHelper();
        addMouseListener(helper);
        addMouseMotionListener(helper);
        setPreferredSize(new Dimension(400, 400));
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(backgroundColor);
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(oldCircleColor);
        for (Circle c : oldCircles) {
            drawCircle(g, c);
        }

        Circle c = newCircle;
        if (c != null) {
            g.setColor(newCircleColor);
            drawCircle(g, c);

            Graphics2D g2 = (Graphics2D) g.create();
            g2.setStroke(DASHED);
            g2.drawLine(c.x, c.y, mouseX, mouseY);
            g2.dispose();
        }
    }

    private void drawCircle(Graphics g, Circle c) {
        // note: drawOval takes top-left corner and diameter, NOT center and radius
        g.drawOval(c.x - c.radius, c.y - c.radius, c.radius * 2, c.radius * 2);
    }
}

并测试它是否有效

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        CirclePanel panel = new CirclePanel();
        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

推荐阅读