我有一个程序,它画了三种不同的形状(圆形、三角形和正方形(,我试着用鼠标拖动它们。我想做的是把点击的形状带到前面。我可以将参数与repaint((一起传递给程序吗?例如,单击的圆必须最后绘制,或者可以创建三种不同的绘制方法来跟踪绘制顺序吗?
另一个问题是我的if循环,如果鼠标在同一区域,拖动正方形穿过圆形和三角形就可以了,但圆形和三角形会带走正方形。我可以在拖动其他图形时关闭鼠标侦听器吗?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Ellipse2D;
import java.awt.Polygon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MouseMoveScale extends JPanel {
public boolean first;
private Rectangle2D.Float myRect = new Rectangle2D.Float(50, 50, 100, 100);
private Ellipse2D.Float myCr = new Ellipse2D.Float(10,10, 100, 100);
private Polygon myTr = new Polygon(new int [] {120, 60, 240}, new int[] {150, 200, 200}, 3);
MovingAdapter ma = new MovingAdapter();
public MouseMoveScale() {
addMouseMotionListener(ma);
addMouseListener(ma);
}
public void paintComponent( Graphics g ) {
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D square = (Graphics2D) g;
Graphics2D triangle = (Graphics2D) g;
Graphics2D circle = (Graphics2D) g;
square.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
square.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
square.setColor(new Color(0, 0, 200));
square.fill(myRect);
triangle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
triangle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
triangle.setColor(new Color(139, 89, 255));
triangle.fill(myTr);
circle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
circle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
circle.setColor(new Color(0, 0, 117));
circle.fill(myCr);
}
class MovingAdapter extends MouseAdapter {
private int x;
private int y;
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - x;
int dy = e.getY() - y;
if (myRect.contains(x, y)) {
myRect.x += dx;
myRect.y += dy;
repaint();
}
else if (myTr.contains(x, y)) {
myTr.translate(dx, dy);
repaint();
}
else if (myCr.contains(x, y)) {
myCr.x += dx;
myCr.y += dy;
repaint();
}
x += dx;
y += dy;
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Shapes World");
MouseMoveScale m = new MouseMoveScale();
m.setDoubleBuffered(true);
frame.add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
建议:
- 将所有形状放入
List<Shape>
- 在paintComponent中向前遍历列表,绘制每个形状。最后一个抽到的将在上面
- 在鼠标侦听器/适配器中,向后遍历形状列表,找出按下的形状,并在找到任何形状后立即退出循环。倒过来做,这样上面的那个先检查一下
- 找到形状后,将其从列表中删除,然后重新添加并调用
repaint()
。这会把它画在上面
例如:
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.Shape;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class DragShapes extends JPanel {
private static final Color Background = Color.WHITE;
private int panelWidth;
private int panelHeight;
private List<ColorShape> shapes = new ArrayList<>();
public DragShapes(int width, int height, int diskCount) {
this.panelWidth = width;
this.panelHeight = height;
setBackground(Background);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
double satVariance = 0.4;
for (int i = 0; i < diskCount; i++) {
// create some semi-random colors
float hue = ((float) i) / (float) diskCount;
float brightness = (float) (satVariance * Math.random() + 1 - satVariance);
float saturation = (float) (satVariance * Math.random() + 1 - satVariance);
Color color = Color.getHSBColor(hue, saturation, brightness);
// create random placement
int x = (int) (Math.random() * (width - ColorShape.WIDTH) + ColorShape.WIDTH / 2);
int y = (int) (Math.random() * (height - ColorShape.WIDTH) + ColorShape.WIDTH / 2);
// create random Color Shapes using the above locations and colors
shapes.add(new ColorShape(color, x, y));
}
}
@Override
protected void paintComponent(Graphics g) {
// do JPanel house-keeping painting
super.paintComponent(g);
// create smooth curves
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// iterate through the shapes list, drawing each shape
for (ColorShape colorShape : shapes) {
colorShape.draw(g2);
}
}
// size the JPanel appropriately
@Override
public Dimension getPreferredSize() {
Dimension prefSize = super.getPreferredSize();
if (isPreferredSizeSet()) {
return prefSize;
}
int w = Math.max(prefSize.width, panelWidth);
int h = Math.max(prefSize.height, panelHeight);
return new Dimension(w, h);
}
// combination mouse listener and mouse motion listener
private class MyMouse extends MouseAdapter {
private ColorShape colorShape; // the current color shape that we're dragging
private Point p; // previous location of the color shape
@Override
public void mousePressed(MouseEvent e) {
// iterate *backward* through the list
for (int i = shapes.size() - 1; i >= 0; i--) {
// get the shape in the list
ColorShape colorShape = shapes.get(i);
// if it contains the current point, we've got it!
if (colorShape.contains(e.getPoint())) {
// set the mouse adapter colorShape field with this shape
this.colorShape = colorShape;
// set the current point, p
this.p = e.getPoint();
// *remove* the shape from the list
shapes.remove(colorShape);
// re-add it so it is now the last shape in the list
shapes.add(colorShape);
// draw all shapes
repaint();
return; // we're done
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
moveShape(e); // move the dragged shape
colorShape = null; // and release the reference to it
}
@Override
public void mouseDragged(MouseEvent e) {
moveShape(e); // move the dragged shape
}
private void moveShape(MouseEvent e) {
// if we are not currently dragging a shape
if (colorShape == null) {
return; // get out of here
}
// otherwise translate this shape using the 2 points
colorShape.translate(p, e.getPoint());
repaint();
// re-set the current point
p = e.getPoint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
int width = 1000;
int height = 800;
int diskCount = 40;
JFrame frame = new JFrame("Drag Shapes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DragShapes(width, height, diskCount));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class ColorShape {
public static final int WIDTH = 100;
private Color color;
private int x;
private int y;
// path 2d objects are Shape objects that can be translated
// easily using an affine transform
private Path2D path;
public ColorShape(Color color, int x, int y) {
super();
this.color = color;
this.x = x;
this.y = y;
// create an ellipse (circle) and make a Path2D object with it
Shape shape = new Ellipse2D.Double(x - WIDTH / 2, y - WIDTH / 2, WIDTH, WIDTH);
path = new Path2D.Double(shape);
}
// test if the point is contained by this shape
public boolean contains(Point p) {
return path.contains(p);
}
// draw our shape
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill(path);
g2.setColor(Color.BLACK);
g2.draw(path);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public static int getWidth() {
return WIDTH;
}
public Color getColor() {
return color;
}
// the magic of affine transforms
public void translate(Point p0, Point p1) {
int tx = p1.x - p0.x;
int ty = p1.y - p0.y;
path.transform(AffineTransform.getTranslateInstance(tx, ty));
}
}