Java 使用 Graphics 创建动态但简单的图形

标签 java graphics panel frame

我必须使用 Graphics 类的方法在 Java 中创建图形。我已经编写了 Panel 和 Frame 类的代码,因此我只需使用 Graphics 编写图形即可。

我将添加一张我必须创建的图片,所以也许有人可以帮助我:/

Here´s a picture of the graphic to create

它应该是动态的,因此如果用户更改框架窗口大小,图形也应该是动态的。

请帮我解决这个问题,我已经尝试了很多

最佳答案

我本来打算回答这个问题,作为如何使用分解来解决问题的说明。但图形动态的要求使该应用程序从家庭作业领域转变为组件大小调整的示例。

OP 没有提及他使用什么 GUI 软件来创建图形窗口。我使用 Java Swing 是因为我熟悉 Swing。

这是我创建的 GUI。我将在答案末尾发布可运行的代码,以便您可以自己运行它并查看组件大小的调整。

Graphics Example

当面对这样的任务时,您将问题分解为越来越小的步骤,直到您可以为每个步骤编写代码。我就是这么做的。

正如我在评论中所说,该图形由 6 个级别的 4 个圆圈组成。这些圆圈通过接触其圆周的线连接起来。因此,使用model / view / controller模式,我创建了一个模型。

我定义的第一件事是 Circle 类。我的圆类包含一个整数半径和一个 java.awt.Point 中心。 Point 是一个保存 X 和 Y 值的类。

我的 Circle 类有一个绘制方法,可以使用 Graphics drawOval 方法绘制圆。我将绘制方法放在 Circle 类中,以保持其他绘制方法的简单。当生成复杂的图形或动画游戏时,让每个对象自行绘制。

Circle 类有四种方法来确定圆周上的顶点、右点、底点和左点。当我们绘制连接圆的线时将使用这些方法。

这是完整的 Circle 类。

public class Circle {

    private int radius;

    private Point center;

    public int getRadius() {
        return radius;
    }

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

    public Point getCenter() {
        return center;
    }

    public void setCenter(Point center) {
        this.center = center;
    }

    public Point getTopPoint() {
        int x = getCenter().x;
        int y = getCenter().y - getRadius();
        return new Point(x, y);
    }

    public Point getRightPoint() {
        int x = getCenter().x + getRadius();
        int y = getCenter().y;
        return new Point(x, y);
    }

    public Point getBottomPoint() {
        int x = getCenter().x;
        int y = getCenter().y + getRadius();
        return new Point(x, y);
    }

    public Point getLeftPoint() {
        int x = getCenter().x - getRadius();
        int y = getCenter().y;
        return new Point(x, y);
    }

    public void draw(Graphics g) {
        int diameter = getRadius() + getRadius();
        int x = getCenter().x - getRadius();
        int y = getCenter().y - getRadius();
        g.drawOval(x, y, diameter, diameter);
    }

}

接下来,我创建了一个类来容纳四个圆圈。

我的 CircleLevel 类有一个绘制方法,可以绘制四个圆和连接线。这里就不多解释了。

public class CircleLevel {

    private int radius;
    private int drawingWidth;

    private Circle topLeftCircle;
    private Circle topRightCircle;
    private Circle bottomLeftCircle;
    private Circle bottomRightCircle;

    public CircleLevel(int drawingWidth) {
        this.drawingWidth = drawingWidth;

        this.topLeftCircle = new Circle();
        this.topRightCircle = new Circle();
        this.bottomLeftCircle = new Circle();
        this.bottomRightCircle = new Circle();
    }

    public int getRadius() {
        return radius;
    }

    public int getDrawingWidth() {
        return drawingWidth;
    }

    public void setDrawingWidth(int drawingWidth) {
        this.drawingWidth = drawingWidth;
    }

    public void createCircles(int radius) {
        this.radius = radius;
        int center = drawingWidth / 2;

        Point point = new Point(center - radius, center - radius);
        topLeftCircle.setCenter(point);
        topLeftCircle.setRadius(radius);

        point = new Point(center + radius, center - radius);
        topRightCircle.setCenter(point);
        topRightCircle.setRadius(radius);

        point = new Point(center - radius, center + radius);
        bottomLeftCircle.setCenter(point);
        bottomLeftCircle.setRadius(radius);

        point = new Point(center + radius, center + radius);
        bottomRightCircle.setCenter(point);
        bottomRightCircle.setRadius(radius);
    }

    public void draw(Graphics g) {
        topLeftCircle.draw(g);
        topRightCircle.draw(g);
        bottomLeftCircle.draw(g);
        bottomRightCircle.draw(g);

        drawLines(g);
    }

    private void drawLines(Graphics g) {
        Point start = topLeftCircle.getTopPoint();
        Point end = topRightCircle.getTopPoint();
        g.drawLine(start.x, start.y, end.x, end.y);

        start = topRightCircle.getRightPoint();
        end = bottomRightCircle.getRightPoint();
        g.drawLine(start.x, start.y, end.x, end.y);

        start = bottomRightCircle.getBottomPoint();
        end = bottomLeftCircle.getBottomPoint();
        g.drawLine(start.x, start.y, end.x, end.y);

        start = bottomLeftCircle.getLeftPoint();
        end = topLeftCircle.getLeftPoint();
        g.drawLine(start.x, start.y, end.x, end.y);
    }
}

View 和 Controller 代码更加复杂。我通过扩展 java.awt.event.ComponentAdapter 创建了一个 FrameResize 类。我通过扩展 JPanel 创建了一个绘图面板。

因为我先创建 GUI,然后绘制图形,所以我必须在 FrameResize 和绘图面板类中放置 boolean 标志,以便我可以先创建模型,然后让 View 绘制图形。

无论如何,如果您已经读到这里,这里是可运行的代码。这不是最小的。

import java.awt.BasicStroke;
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.ComponentAdapter;
import java.awt.event.ComponentEvent;

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

public class GraphicsExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new GraphicsExample());
    }

    private static final boolean DEBUG = false;

    private int drawingWidth;

    private CircleLevel[] circleLevels;

    private Dimension frameSize;

    private DrawingPanel drawingPanel;

    private JFrame frame; 

    public GraphicsExample() {
        this.drawingWidth = 400;
    }

    @Override
    public void run() {
        frame = new JFrame("Graphics Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        FrameResize frameResize = new FrameResize();
        frame.addComponentListener(frameResize);

        drawingPanel = new DrawingPanel(drawingWidth);
        frame.add(drawingPanel);

        frame.pack();
        frame.setLocationRelativeTo(null);

        drawingPanel.setCreated(true);
        circleLevels = drawGraphics();
        drawingPanel.repaint();

        frameSize = frame.getSize();
        if (DEBUG) System.out.println(frameSize);

        frame.setVisible(true);
        frameResize.setCreated(true);
    }

    private CircleLevel[] drawGraphics() {
        int levels = 6;
        CircleLevel[] circleLevels = new CircleLevel[levels];

        int margin = 6;
        int width = drawingWidth - margin - margin;
        int decrement = drawingWidth / 8;

        for (int i = 0; i < levels; i++) {
            int radius = width / 4;
            CircleLevel circleLevel = new CircleLevel(drawingWidth);
            circleLevel.createCircles(radius);
            circleLevels[i] = circleLevel;
            width -= decrement;
        }

        return circleLevels;
    }

    public class FrameResize extends ComponentAdapter {

        private boolean isCreated;

        public FrameResize() {
            this.isCreated = false;
        }

        public void setCreated(boolean isCreated) {
            this.isCreated = isCreated;
        }

        @Override
         public void componentResized(ComponentEvent event) {
            if (isCreated) {
                Dimension size = event.getComponent().getSize();
                if (size.width == frameSize.width && 
                        size.height == frameSize.height) {
                    return;
                }

                if (DEBUG) System.out.println(size);
                frame.setVisible(false);
                frameSize = size;

                drawingWidth = calculateDrawingSize();
                drawingPanel.setResized(drawingWidth);
                drawingPanel.revalidate();
                circleLevels = drawGraphics();
                drawingPanel.repaint();
                frame.setVisible(true);
            }
        }

        private int calculateDrawingSize() {
            // You'll have to adjust these borders for
            // different operating systems.  I'm using
            // Windows 10 defaults.
            int borderWidth = 16;
            int borderHeight = 39;
            int width = frameSize.width - borderWidth;
            int height = frameSize.height - borderHeight;
            int drawingWidth = Math.min(width, height);
            // Making sure the drawing width is divisible
            // by 8 makes subsequent calculations even.
            return drawingWidth / 8 * 8;
        }

    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private boolean isResized;
        private boolean isCreated;

        private int width;

        public DrawingPanel(int width) {
            this.setBackground(Color.WHITE);
            this.setPreferredSize(new Dimension(width, width));
            this.width = width;
            this.isResized = false;
            this.isCreated = false;
        }

        public void setCreated(boolean isCreated) {
            this.isCreated = isCreated;
        }

        public void setResized(int width) {
            this.setPreferredSize(new Dimension(width, width));
            this.width = width;
            this.isResized = true;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

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

            if (isResized) {
                g2d.setColor(Color.WHITE);
                g2d.fillRect(0, 0, width, width);
                isResized =  false;
            }

            if (isCreated) {
                g2d.setColor(Color.BLACK);
                g2d.setStroke(new BasicStroke(2f));
                for (CircleLevel circleLevel : circleLevels) {
                    circleLevel.draw(g);
                }
            }
        }

    }

    public class CircleLevel {

        private int radius;
        private int drawingWidth;

        private Circle topLeftCircle;
        private Circle topRightCircle;
        private Circle bottomLeftCircle;
        private Circle bottomRightCircle;

        public CircleLevel(int drawingWidth) {
            this.drawingWidth = drawingWidth;

            this.topLeftCircle = new Circle();
            this.topRightCircle = new Circle();
            this.bottomLeftCircle = new Circle();
            this.bottomRightCircle = new Circle();
        }

        public int getRadius() {
            return radius;
        }

        public int getDrawingWidth() {
            return drawingWidth;
        }

        public void setDrawingWidth(int drawingWidth) {
            this.drawingWidth = drawingWidth;
        }

        public void createCircles(int radius) {
            this.radius = radius;
            int center = drawingWidth / 2;

            Point point = new Point(center - radius, center - radius);
            topLeftCircle.setCenter(point);
            topLeftCircle.setRadius(radius);

            point = new Point(center + radius, center - radius);
            topRightCircle.setCenter(point);
            topRightCircle.setRadius(radius);

            point = new Point(center - radius, center + radius);
            bottomLeftCircle.setCenter(point);
            bottomLeftCircle.setRadius(radius);

            point = new Point(center + radius, center + radius);
            bottomRightCircle.setCenter(point);
            bottomRightCircle.setRadius(radius);
        }

        public void draw(Graphics g) {
            topLeftCircle.draw(g);
            topRightCircle.draw(g);
            bottomLeftCircle.draw(g);
            bottomRightCircle.draw(g);

            drawLines(g);
        }

        private void drawLines(Graphics g) {
            Point start = topLeftCircle.getTopPoint();
            Point end = topRightCircle.getTopPoint();
            g.drawLine(start.x, start.y, end.x, end.y);

            start = topRightCircle.getRightPoint();
            end = bottomRightCircle.getRightPoint();
            g.drawLine(start.x, start.y, end.x, end.y);

            start = bottomRightCircle.getBottomPoint();
            end = bottomLeftCircle.getBottomPoint();
            g.drawLine(start.x, start.y, end.x, end.y);

            start = bottomLeftCircle.getLeftPoint();
            end = topLeftCircle.getLeftPoint();
            g.drawLine(start.x, start.y, end.x, end.y);
        }
    }

    public class Circle {

        private int radius;

        private Point center;

        public int getRadius() {
            return radius;
        }

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

        public Point getCenter() {
            return center;
        }

        public void setCenter(Point center) {
            this.center = center;
        }

        public Point getTopPoint() {
            int x = getCenter().x;
            int y = getCenter().y - getRadius();
            return new Point(x, y);
        }

        public Point getRightPoint() {
            int x = getCenter().x + getRadius();
            int y = getCenter().y;
            return new Point(x, y);
        }

        public Point getBottomPoint() {
            int x = getCenter().x;
            int y = getCenter().y + getRadius();
            return new Point(x, y);
        }

        public Point getLeftPoint() {
            int x = getCenter().x - getRadius();
            int y = getCenter().y;
            return new Point(x, y);
        }

        public void draw(Graphics g) {
            int diameter = getRadius() + getRadius();
            int x = getCenter().x - getRadius();
            int y = getCenter().y - getRadius();
            g.drawOval(x, y, diameter, diameter);
        }

    }

}

关于Java 使用 Graphics 创建动态但简单的图形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61246446/

相关文章:

ExtJS:如何使用 BorderLayout 扩展 Ext.Panel?

java - 获取mybatis最后插入记录的id

java - 使用 AXIS2 java2wsdl 工具生成 wsdl

Java多线程: program sporadically strats using more cores than a FixedThreadPool is allowed to

java - 为什么我的图像没有充满绿色?

java - mouseMoved(MouseEvent e) 跟不上程序逻辑

java - JTable 列未出现

java - 创建自定义绘制方法 - Graphics 2D g2 为空

html - 如何在 Bootstrap 面板中拆分 'title' 和 'icon'?

python - Pandas :具有多个索引的滚动总和(即面板数据)