【问题标题】:How do I properly implement a mouselistener to my Jcomponent?如何正确地为我的 Jcomponent 实现鼠标侦听器?
【发布时间】:2021-06-11 02:02:13
【问题描述】:

我有一个项目,我需要在 Java 中创建一个 GUI,该 GUI 在鼠标单击时创建一个圆圈,并在鼠标拖过框架时继续制作尾随圆圈。我在这里得到了多个线程的参考,但似乎没有一个可以帮助我做我需要做的事情。到目前为止,我的 JFrame 中添加了一个静态圆圈,但我想让多个圆圈显示在该框架中的 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, 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
    
}

}

【问题讨论】:

    标签: java swing jpanel repaint mouselistener


    【解决方案1】:

    这是我整理的 GUI。

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

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

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

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

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

    Circles 类拥有 ListCircle 实例。

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

    控制器类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;
            }
            
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      这里的想法是:

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

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

      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() {
      
          }
      
      }
      

      【讨论】:

      • 感谢您的帮助。我不明白需要 WindowListener,为什么要添加它?
      • 您可以看到在 initlistener 方法调用 sonitnisnsafe 期间设置了鼠标和 drsg 侦听器,以便在应用程序关闭时将其删除。
      猜你喜欢
      • 2017-04-19
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 2019-11-26
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多