簡體   English   中英

如何正確地為我的 Jcomponent 實現鼠標偵聽器?

[英]How do I properly implement a mouselistener to my Jcomponent?

我有一個項目,我需要在 Java 中創建一個 GUI,在鼠標單擊時創建一個圓圈,並在鼠標拖過框架時繼續制作尾隨圓圈。 我在這里得到了多個線程的參考,但似乎沒有一個可以幫助我做我需要做的事情。 到目前為止,我已經在 JFrame 中添加了一個 static 圓圈,但我想讓多個圓圈顯示在該框架中的 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
    
}

}

這是我放在一起的 GUI。

圓圈圖形用戶界面

每次鼠標單擊都會創建一個圓圈。

When I create a Swing GUI, or any Java application, I use the model / view / controller (MVC) pattern. 這種模式使我能夠分離我的關注點並一次專注於應用程序的一個部分。

對於 Swing GUI,MVC 模式意味着:

  1. 該視圖從 model 讀取。
  2. 該視圖不會更新 model。
  3. controller 更新 model 並重新繪制/重新驗證視圖。

model 包含兩個類, CirclesCircle Circle class 定義了一個具有Point中心、 int半徑和Color顏色的圓。 因為Circle是 class,所以我可以定義任意數量的實例(圓)。

Circles class 包含一個Circle實例List

該視圖由JFrame和繪圖JPanel組成。 繪圖JPanelpaintComponent方法繪制圓圈。 時期。 我們在 controller class 中創建圓圈。

controller class CirclesListener創建圓圈並重新繪制繪圖JPanel 每次重新繪制繪圖JPanel時,都會重新繪制所有圓圈。

An instance of the JFrame class and the application model class is passed to the controller CirclesListener class. 這允許 class 創建一個新圓圈並重新繪制繪圖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, %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() {

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM