简体   繁体   English

单击鼠标后在JPanel上绘制圆圈

[英]Draw circle on JPanel after mouse click

I want to draw circle only after mouse gets click. 我只想在鼠标单击后绘制圆圈。 As paintComponent method called itself, so first circle draw without click. 由于paintComponent方法调用了自身,因此首先绘制圆而无需单击。

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

public DrawPanel() {
    setBackground(Color.WHITE);
    addMouseListener(this);
}

public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.red);
    g2.fillOval(x, y, 20, 20);
}

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

}

There are a few issues with your code: 您的代码存在一些问题:

  1. You never call super.paintComponent(); 您永远不会调用super.paintComponent();
  2. You only have one x and y 你只有一个xy
  3. Note how when you resize the frame, some circles will disappear and it overall behaves in a strange way. 请注意,当您调整框架大小时,某些圆圈将消失,并且总体上以奇怪的方式表现。
  4. I would store all the Point s where the user has clicked in an ArrayList and then loop through that list inside the paintComponent method. 我会将用户单击的所有Point都存储在ArrayList ,然后在paintComponent方法内遍历该列表。 This way you can call super.paintComponent(); 这样,您可以调用super.paintComponent(); without the circles disappearing. 没有圆圈消失。

Changed, working code: 更改后的工作代码:

import java.awt.Color;
import java.awt.EventQueue;
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 javax.swing.JFrame;
import javax.swing.JPanel;

public class DrawPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private ArrayList<Point> points;

    public DrawPanel() {
        points = new ArrayList<Point>();
        setBackground(Color.WHITE);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                points.add(new Point(e.getX(), e.getY()));
                repaint();
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.red);
        for (Point point : points) {
            g2.fillOval(point.x, point.y, 20, 20);
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new DrawPanel());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(400, 400);
                frame.setVisible(true);
            }
        });
    }

}

You should have some initial state, so you know not to draw when it is set. 您应该具有一些初始状态,因此您知道在设置时不会绘制。

This can be done with an easy boolean variable, that you set to true when the user has pressed on the screen. 这可以通过一个简单的布尔变量来完成,您可以在用户按下屏幕时将其设置为true。

public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
int x, y;
boolean mustDraw = false;

public DrawPanel() {
    setBackground(Color.WHITE);
    addMouseListener(this);
}

public void paintComponent(Graphics g) {
    if(!mustDraw) return;
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.red);
    g2.fillOval(x, y, 20, 20);
}

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

}

You should place your circle inside its own class. 您应该将圈子放入自己的班级中。 That class will hold information on its location, radius, and its color. 该类将保存有关其位置,半径和颜色的信息。 You can abstract your shape and have a list of shapes to draw on the panel. 您可以提取形状,并在面板上绘制一系列形状。 This will make it easy to implement a triangle, square, hexagon, etc. later. 这将使以后易于实现三角形,正方形,六边形等变得容易。

You can add more methods and attributes to your shape objects later and only have to change their internal implementation of THEIR OWN paintComponent(g) method. 以后可以向形状对象添加更多方法和属性,而只需更改其对IRIR OWN paintComponent(g)方法的内部实现。 This makes the DrawPanel depend on how each Shape does its own drawing. 这使得DrawPanel取决于每个Shape如何进行自己的绘图。

应用截图


App.java App.java

import java.awt.Dimension;

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

public class App {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame("Circle Click Application");
                DrawPanel p = new DrawPanel(10f);

                p.setPreferredSize(new Dimension(300, 200));;

                f.setContentPane(p);
                f.pack();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

DrawPanel.java DrawPanel.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class DrawPanel extends JPanel implements MouseListener {
    private static final long serialVersionUID = -6817035652787391530L;

    private List<Shape> shapes;
    protected float radius;

    private float sat = 0.7f;
    private float bri = 0.8f;

    public DrawPanel(float radius) {
        this.shapes = new ArrayList<Shape>();
        this.radius = radius;

        setBackground(Color.WHITE);
        addMouseListener(this);
    }

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

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        for (Shape shape : shapes) {
            shape.paintComponent(g);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        shapes.add(new Circle(e.getX(), e.getY(), radius, ColorUtils.randHue(sat, bri)));

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

Shape.java Shape.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

public interface Shape {
    Point getOrigin();
    void setOrigin(Point origin);

    Color getColor();
    void setColor(Color color);

    void paintComponent(Graphics g);
}

Circle.java Circle.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

public class Circle implements Shape {
    private Point origin;
    private float radius;
    private Color color;

    public Circle() {
        this(0, 0, 0.5f, Color.BLACK);
    }

    public Circle(int x, int y, float radius, Color color) {
        this(new Point(x, y), radius, color);
    }

    public Circle(Point origin, float radius, Color color) {
        this.origin = origin;
        this.radius = radius;
        this.color = color;
    }

    @Override
    public Point getOrigin() {
        return origin;
    }

    @Override
    public void setOrigin(Point origin) {
        this.origin = origin;
    }

    public float getRadius() {
        return radius;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    @Override
    public Color getColor() {
        return color;
    }

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

    @Override
    public void paintComponent(Graphics g) {
        int diameter = (int) (this.radius * 2);
        int x = (int) (origin.x - this.radius);
        int y = (int) (origin.y - this.radius);

        g.setColor(this.color);
        g.fillOval(x, y, diameter, diameter);
    }
}

ColorUtils.java ColorUtils.java

import java.awt.Color;
import java.util.Random;

public class ColorUtils {
    private static final Random RAND;

    static {
        RAND = new Random(System.currentTimeMillis());
    }

    public static Color randHue(float saturation, float brightness) {
        return Color.getHSBColor(RAND.nextFloat(), saturation, brightness);
    }
}

Extension 延期

You can easily add a class such as a Triangle just by implementing the Shape interface. 您只需实现Shape接口就可以轻松添加一个类,例如Triangle

DrawPanel#mouseClicked DrawPanel#mouseClicked

@Override
public void mouseClicked(MouseEvent e) {
    long time = System.currentTimeMillis();
    boolean isEven = time % 2 == 0;

    if (isEven) {
        shapes.add(new Circle(e.getX(), e.getY(), radius, ColorUtils.randHue(sat, bri)));
    } else {
        shapes.add(new Triangle(e.getX(), e.getY(), radius * 2, ColorUtils.randHue(sat, bri)));
    }

    repaint();
}

Triangle.java Triangle.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.Point2D;

public class Triangle implements Shape {
    private Point origin;
    private float side;
    private Color color;

    private Polygon poly;

    public Triangle(int x, int y, float side, Color color) {
        this(new Point(x, y), side, color);
    }

    public Triangle(Point origin, float side, Color color) {
        this.origin = origin;
        this.side = side;
        this.color = color;

        recalculate();
    }

    protected void recalculate() {
        this.poly = createPolygon((float) origin.getX(), (float) origin.getY(), side, false);
    }

    protected Polygon createPolygon(float x, float y, float side, boolean invert) {
        float xOff = side / 2f;
        float yOff = (float) (xOff * Math.sqrt(3));

        float r1 = 1f / 3f;
        float r2 = 2f / 3f;

        if (invert) {
            yOff *= -1;
        }

        return createPolygon(new Point2D.Float[] {
            new Point2D.Float(x,        y - (yOff * r2)), // Top
            new Point2D.Float(x - xOff, y + (yOff * r1)), // Left
            new Point2D.Float(x + xOff, y + (yOff * r1))  // Right
        });
    }

    protected Polygon createPolygon(Point2D.Float[] points) {
        int nPoints = points.length + 1;
        int xCoords[] = new int[nPoints];
        int yCoords[] = new int[nPoints];

        for (int i = 0; i < nPoints; i++) {
            xCoords[i] = (int) points[i % points.length].x;
            yCoords[i] = (int) points[i % points.length].y;
        }

        return new Polygon(xCoords, yCoords, nPoints);
    }

    @Override
    public Point getOrigin() {
        return origin;
    }

    @Override
    public void setOrigin(Point origin) {
        this.origin = origin;

        recalculate();
    }

    public float getSide() {
        return side;
    }

    public void setSide(float side) {
        this.side = side;

        recalculate();
    }

    @Override
    public Color getColor() {
        return color;
    }

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

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(this.color);
        g.fillPolygon(poly);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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