简体   繁体   中英

How do I properly implement a mouselistener to my Jcomponent?

I have a project where I need to create a GUI in Java that creates a circle on mouse-click and and continues to make trailing circles as the mouse is dragged through the frame. I've been given reference to multiple threads on here but none have seemed to help me do what I need to do. So far I've got a static circle added to my JFrame, but I want to make the multiple circles show on a JPanel in that frame. I'm stuck after trying many different angles. As of now I just need to be able to click once and create a circle.

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, 0, 0, 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
    
}

}

Here's a GUI that I put together.

圆圈图形用户界面

Each mouse click creates a circle.

When I create a Swing GUI, or any Java application, I use the model / view / controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.

For a Swing GUI, the MVC pattern means:

  1. The view reads from the model.
  2. The view does not update the model.
  3. The controller updates the model and repaints / revalidates the view.

The model consists of two classes, Circles and Circle . The Circle class defines a circle with a Point center, int radius, and a Color color. Because Circle is a class, I can define as many instances (circles) as I want.

The Circles class holds a List of Circle instances.

The view consists of a JFrame and a drawing JPanel . The paintComponent method of the drawing JPanel paints circles. Period. We create the circles in the controller class.

The controller class CirclesListener creates the circles and repaints the drawing JPanel . All of the circles are redrawn each and every time the drawing JPanel is repainted.

An instance of the JFrame class and the application model class is passed to the controller CirclesListener class. This allows the class to create a new circle and repaint the drawing JPanel .

Here's the complete runnable code.

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;
        }
        
    }

}

The idea here is to:

  • capture point
  • add it to list
  • repaint component

Here is how I have done it, this is a sample code.

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, %f)", x, y);
        System.out.println("Mouse Dragged @ " + cordinates);
        System.out.println("Mouse Dragged @ " + shapeList.size());
        shapeList.add(new CircleData(new Rectangle((int) x, (int) y, 50, 50), 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() {

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM