java 鼠标点击后在JPanel上画圆

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35299786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:58:54  来源:igfitidea点击:

Draw circle on JPanel after mouse click

javaswing

提问by Ranjeet

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

}

回答by Lukas Rotter

There are a few issues with your code:

您的代码存在一些问题:

  1. You never call super.paintComponent();
  2. You only have one xand y
  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 Points where the user has clicked in an ArrayListand then loop through that list inside the paintComponentmethod. This way you can call super.paintComponent();without the circles disappearing.
  1. 你从不打电话 super.paintComponent();
  2. 你只有一个xy
  3. 请注意,当您调整框架大小时,一些圆圈会消失,并且整体表现出一种奇怪的方式。
  4. 我将存储Point用户在其中单击的所有s,ArrayList然后在paintComponent方法内循环遍历该列表。这样您就可以super.paintComponent();在圆圈不消失的情况下拨打电话。

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

}

回答by Mr. Polywhirl

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. This makes the DrawPaneldepend on how each Shapedoes its own drawing.

您可以稍后向形状对象添加更多方法和属性,而只需更改它们自己的paintComponent(g)方法的内部实现。这DrawPanel取决于每个Shape人如何进行自己的绘图。

App screenshot

应用截图



App.java

应用程序.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

绘制面板.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

形状.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

圆环.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

颜色实用程序

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 Trianglejust by implementing the Shapeinterface.

您可以Triangle通过实现Shape接口轻松添加诸如just 之类的类。

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

三角形.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);
    }
}

回答by Ferrybig

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

}