是否可以将在 paintComponent 中创建的多个对象设置为一个整体变量?即由矩形、直线和椭圆组成的脸

Is it possible to set multiple objects created in paintComponent to one whole variable? i.e. A face made up of a rectangle, line and ellipse

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.JComponent;

/*
 * This component will draw an "Alien" face
 */ 

public class FaceComponent extends JComponent 
{

//Create a constructor that will create a face and place it in a variable.

public void paintComponent(Graphics g)
{
    //Recover Graphics2D
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;

    //Construct the alien face

    //Draw the  head
    Ellipse2D.Double head = new Ellipse2D.Double (5, 80, 100, 150);
    g2.draw(head);

    //Draw the set of eyes
    g2.setColor(Color.GREEN);
    Rectangle eye = new Rectangle(25, 140, 15, 15);
    g2.fill(eye);
    eye.translate(50, 0);
    g2.fill(eye);

    //Draw the mouth
    Line2D.Double mouth = new Line2D.Double(30, 180, 80, 180);
    g2.setColor(Color.RED);
    g2.draw(mouth);

    //Draw the greeting
    g2.setColor(Color.BLUE);
    g2.drawString("Hello, World!", 20, 245);
}
}

我想将创建的这个 "face" 分配给一个 public 值,并将其设置为 x 和 y 坐标,这样当我为我的移动创建方法时 class,我将能够使用循环移动脸部。

我想不出更好的方法来做到这一点,如果有人能够用不同的方法启发我,我会非常愿意自己找出答案。只是想找人给我指明正确的方向。

是的,很有可能将 Shape 对象组合成一个复合对象,例如 Path2D 对象,但是您会丢失颜色信息。最好将你的脸画到 BufferedImage 上,换句话说,用它制作一个 "sprite",然后你可以随意移动它。

例如,

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

@SuppressWarnings("serial")
public class FacePanel extends JPanel {
    private static final int PREF_W = 1000;
    private static final int PREF_H = 800;
    private static final int BI_W = 200;
    private static final int BI_H = 300;
    private Ellipse2D.Double head = new Ellipse2D.Double(5, 5, 100, 150);
    private Rectangle eye = new Rectangle(25, 65, 15, 15);
    private BufferedImage faceSprite = null;
    private int faceX = 0;
    private int faceY = 0;

    public FacePanel() {
        faceSprite = createFaceSprite();
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    private BufferedImage createFaceSprite() {
        BufferedImage img = new BufferedImage(BI_W, BI_H, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Draw the head
        g2.draw(head);

        // Draw the set of eyes
        g2.setColor(Color.GREEN);
        g2.fill(eye);
        eye.translate(50, 0);
        g2.fill(eye);

        // Draw the mouth
        Line2D.Double mouth = new Line2D.Double(30, 105, 80, 105);
        g2.setColor(Color.RED);
        g2.draw(mouth);

        // Draw the greeting
        g2.setColor(Color.BLUE);
        g2.drawString("Hello, World!", 20, 170);
        g2.dispose();
        return img;
    }

    // mouse listener and motion listener to allow us to move the face
    private class MyMouse extends MouseAdapter {
        private Point p0 = null; // location of initial mouse press
        private Point img0 = null; // initial location of face

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                // if not the left mouse button, return
                return;
            }

            p0 = e.getPoint();
            Point p = new Point(p0.x - faceX, p0.y - faceY);
            if (!head.contains(p)) {
                // if not pressing inside of head, return
                p0 = null;
                return;
            }

            img0 = new Point(faceX, faceY);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (p0 != null && img0 != null) {
                moveFace(e);
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (p0 != null && img0 != null) {
                moveFace(e);
            }
            p0 = null;
            img0 = null;
        }

        private void moveFace(MouseEvent e) {
            faceX = img0.x + e.getPoint().x - p0.x;
            faceY = img0.y + e.getPoint().y - p0.y;
            repaint();
        }

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (faceSprite != null) {
            g.drawImage(faceSprite, faceX, faceY, this);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private static void createAndShowGui() {
        FacePanel mainPanel = new FacePanel();

        JFrame frame = new JFrame("FacePanel");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

I want to make this "face" that is created assigned to one single public value

'OO' 方法是设计一个 Face class 来理解如何(以及在​​何处)在被请求时绘制 Face。 class 可能如下所示:

class Face {

    private Point location;

    Face(Point location) {
        this.location = location;
    }

    /**
     * @param location the location to set
     */
    public void setLocation(Point location) {
        this.location = location;
    }

    public void draw(Graphics2D g) {
        /* save this to reset it after painting. */
        AffineTransform transform = g.getTransform();        

        AffineTransform move = AffineTransform.getTranslateInstance(
                location.getX(), location.getY());
        g.setTransform(move);

        //Construct the alien face
        //Draw the  head
        g.setColor(Color.DARK_GRAY); // explicitly set a color
        Ellipse2D.Double head = new Ellipse2D.Double(5, 80, 100, 150);
        g.fill(head);
        g.setColor(Color.LIGHT_GRAY);
        g.draw(head);

        //Draw the set of eyes
        g.setColor(Color.GREEN);
        Rectangle eye = new Rectangle(25, 140, 15, 15);
        g.fill(eye);
        eye.translate(50, 0);
        g.fill(eye);

        //Draw the mouth
        Line2D.Double mouth = new Line2D.Double(30, 180, 80, 180);
        g.setColor(Color.RED);
        g.draw(mouth);

        //Draw the greeting
        g.setColor(Color.BLUE);
        g.drawString("Hello, World!", 20, 245);

        // reset the transform to the original (so later painting is not moved)
        g.setTransform(transform);
    }
}

那么FaceComponent class可以简化为:

/*
 * This component will draw "Alien" faces
 */
public class FaceComponent extends JComponent {

    Face[] faces = new Face[3];

    FaceComponent() {
        Random r = new Random();
        for (int ii=0; ii<faces.length; ii++) {
            Point p = new Point(r.nextInt(200), r.nextInt(100));
            faces[ii] = new Face(p);
        }
    }

//Create a constructor that will create a face and place it in a variable.
    public void paintComponent(Graphics g) {
        //Recover Graphics2D
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        for (Face face : faces) {
            face.draw(g2);
        }
    }

    Dimension prefSize = new Dimension(180, 260);

    @Override
    public Dimension getPreferredSize() {
        return prefSize;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JOptionPane.showMessageDialog(null, new FaceComponent());
            }
        };
        SwingUtilities.invokeLater(r);
    }
}