我如何正确地为我的 Jcomponent 实现一个 mouselistener?

问题描述

我有一个项目,我需要在 Java 中创建一个 GUI,该 GUI 在鼠标单击时创建一个圆圈,并在鼠标拖过框架时继续制作尾随圆圈。我已经在这里参考了多个线程,但似乎没有一个能帮助我做我需要做的事情。到目前为止,我已经在 J​​Frame 中添加一个静态圆,但我想让多个圆显示在该框架中的 JPanel 上。在尝试了许多不同的角度后,我被困住了。截至目前,我只需要能够点击一次并创建一个圆圈。

public class Theremin extends JFrame implements ActionListener,MouseListener{
    private JPanel windowArea;
    private int x,y;
private static final long serialVersionUID = 1L;

public Theremin() {
    
}

public static void main(String[] args) {
    Theremin Frame = new Theremin();
    Frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
    MyPanel panel = new MyPanel();
    panel.setLayout(null);
    Frame.add(panel);
    Frame.pack();
    Frame.setLocationRelativeto(null);
    Frame.setVisible(true);
}

private static class MyPanel extends JPanel {

    public void paint(Graphics g) {
        Graphics2D gObj = (Graphics2D)g;
        Shape disk = new Ellipse2D.Double(10,10,100,100);
        gObj.setColor(new Color(255,120));
        gObj.fill(disk);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(700,600);
    }
}

@Override
public void actionPerformed(ActionEvent e) {
    // Todo Auto-generated method stub
    
}

@Override
public void mouseClicked(MouseEvent e) {
    x = e.getX();
    y = e.getY();

    repaint();
}

@Override
public void mousepressed(MouseEvent e) {
    // Todo Auto-generated method stub
    
}

@Override
public void mouseReleased(MouseEvent e) {
    // Todo Auto-generated method stub
    
}

@Override
public void mouseEntered(MouseEvent e) {
    // Todo Auto-generated method stub
    
}

@Override
public void mouseExited(MouseEvent e) {
    // Todo Auto-generated method stub
    
}

}

解决方法

这是我拼凑的图形用户界面。

Circles GUI

每次鼠标点击都会创建一个圆圈。

当我创建 Swing GUI 或任何 Java 应用程序时,我使用 model / view / controller (MVC) 模式。这种模式使我能够将我的关注点分开,并一次专注于应用程序的一个部分。

对于 Swing GUI,MVC 模式意味着:

  1. 视图从模型中读取。
  2. 视图不会更新模型。
  3. 控制器更新模型并重新绘制/重新验证视图。

该模型由两个类组成,CirclesCircleCircle 类定义了一个圆心为 Point、半径为 int 和颜色为 Color 的圆。因为 Circle 是一个类,所以我可以定义任意数量的实例(圆圈)。

Circles 类拥有 ListCircle 实例。

视图由 JFrame 和绘图 JPanel 组成。绘图 paintComponentJPanel 方法绘制圆圈。时期。我们在控制器类中创建圆圈。

控制器类 CirclesListener 创建圆圈并重新绘制绘图 JPanel。每次重新绘制绘图 JPanel 时,都会重新绘制所有圆圈。

JFrame 类和应用程序模型类的实例被传递给控制器​​ CirclesListener 类。这允许类创建一个新圆并重新绘制绘图 JPanel

这是完整的可运行代码。

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

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

public class MouseClickCircleGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MouseClickCircleGUI());
    }
    
    private Circles circles;
    
    private DrawingPanel drawingPanel;
    
    public MouseClickCircleGUI() {
        this.circles = new Circles();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Circles");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        drawingPanel = new DrawingPanel(this,circles);
        frame.add(drawingPanel,BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private final Circles circles;

        public DrawingPanel(MouseClickCircleGUI frame,Circles circles) {
            this.circles = circles;
            setBackground(Color.WHITE);
            setPreferredSize(new Dimension(500,500));
            addMouseListener(new CirclesListener(frame,circles));
        }

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

            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setStroke(new BasicStroke(3f));

            for (Circle circle : circles.getCircles()) {
                Point p = circle.getCenter();
                int radius = circle.getRadius();
                g2.setColor(circle.getColor());
                g2.drawOval(p.x - radius,p.y - radius,2 * radius,2 * radius);
            }
        }

    }
    
    public class CirclesListener extends MouseAdapter {
        
        private final Circles circles;
        
        private final MouseClickCircleGUI frame;
        
        public CirclesListener(MouseClickCircleGUI frame,Circles circles) {
            this.frame = frame;
            this.circles = circles;
        }

        @Override
        public void mouseReleased(MouseEvent event) {
            circles.addCircle(new Circle(event.getPoint(),30,Color.BLACK));
            frame.repaint();
        }

    }
    
    public class Circles {
        
        private final List<Circle> circles;
        
        public Circles() {
            this.circles = new ArrayList<>();
        }
        
        public void addCircle(Circle circle) {
            this.circles.add(circle);
        }

        public List<Circle> getCircles() {
            return circles;
        }
        
    }
    
    public class Circle {
        
        private final int radius;
        
        private final Color color;
        
        private final Point center;

        public Circle(Point center,int radius,Color color) {
            this.center = center;
            this.radius = radius;
            this.color = color;
        }

        public int getRadius() {
            return radius;
        }

        public Point getCenter() {
            return center;
        }

        public Color getColor() {
            return color;
        }
        
    }

}
,

这里的想法是:

  • 捕获点
  • 将其添加到列表中
  • 重绘组件

这是我的做法,这是一个示例代码。

package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Theremin frame = new Theremin();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyPanel panel = new MyPanel();
        panel.initListeners();
        panel.setLayout(null);
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {

            }

            @Override
            public void windowClosing(WindowEvent e) {
                panel.releaseListener();
            }

            @Override
            public void windowClosed(WindowEvent e) {

            }

            @Override
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override
            public void windowActivated(WindowEvent e) {

            }

            @Override
            public void windowDeactivated(WindowEvent e) {

            }
        });
    }
}

class MyPanel extends JPanel implements MouseListener,MouseMotionListener {

    private Graphics graphics;
    private List<CircleData> shapeList = new ArrayList<>();
    private Graphics2D gObj;

    public MyPanel() {
    }

    @Override
    public void paint(Graphics g) {
        this.graphics = g;
        gObj = (Graphics2D) g;
        System.out.println("called paint with times: " + times++);
        for (CircleData circleData : shapeList) {
            Rectangle rectangle = circleData.rectangle;
            Color color = circleData.color;
            Shape disk = new Ellipse2D.Double(rectangle.x,rectangle.y,rectangle.width,rectangle.height);
            gObj.setColor(color);
            gObj.fill(disk);
        }
    }


    Color randomColor() {
        int red = (int) (Math.random() * 256);
        int green = (int) (Math.random() * 256);
        int blue = (int) (Math.random() * 256);
        return new Color(red,green,blue);
    }

    static int times = 0;


    @Override
    public Dimension getPreferredSize() {
        return new Dimension(700,600);
    }

    public void initListeners() {
        System.out.println("added default listeners");
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void releaseListener() {
        System.out.println("removed default listeners");
        removeMouseListener(this);
        removeMouseMotionListener(this);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        float x = e.getX();
        float y = e.getY();
        String cordinates = String.format("(%f,%f)",x,y);
        System.out.println("Mouse Clicked @ " + cordinates);
        shapeList.add(new CircleData(new Rectangle((int) x,(int) y,50,50),randomColor()));
        repaint();
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        float x = e.getX();
        float y = e.getY();
        String cordinates = String.format("(%f,y);
        System.out.println("Mouse Dragged @ " + cordinates);
        System.out.println("Mouse Dragged @ " + shapeList.size());
        shapeList.add(new CircleData(new Rectangle((int) x,randomColor()));
        repaint();
    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }
}

class CircleData {
    Rectangle rectangle;
    Color color;

    public CircleData(Rectangle rectangle,Color color) {
        this.rectangle = rectangle;
        this.color = color;
    }
}

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

    public Theremin() {

    }

}