簡體   English   中英

Java awt 圍繞圓圈繪制元素

[英]Java awt draw elements around a circle

我目前正在寫一個小游戲,我遇到了一個問題。 我需要在一個大圓圈的邊緣畫 64 個小圓圈。 所以我想要這樣的東西:

64個圓圈圍繞一個大圓圈排列

我已經嘗試了很多東西,但它們沒有奏效。 How can this be done in java, using the java.awt.Component#paint() method and the java.awt.Graphics class?

謝謝。

因此,您的基本問題歸結為“根據給定角度在圓上找到一個點”

一個快速的谷歌會找到像Find the coordinates of a point on a circle 之類的資源,坦率地說,我是個白痴,所以我會縮小搜索范圍以包括 Java,這會給我們類似如何計算使用 Java 的圓中點的坐標? - 甜的。

所以基本計算可能看起來像

double xPosy = Math.cos(rads) * radius);
double yPosy = Math.sin(rads) * radius);

現在,這解決了您問題的核心方面。 rest 歸結為簡單地繪制結果。 請參閱在 AWT 和 Swing執行自定義繪畫和繪畫作為起點和2D 圖形,以更詳細地了解 API。

現在,考慮到上述所有因素,您最終可能會得到一個類似於...的解決方案

在此處輸入圖像描述

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int midX = getWidth() / 2;
            int midY = getHeight() / 2;
            Dimension size = new Dimension(4, 4);
            g2d.setColor(Color.BLACK);
            for (int index = 0; index < 64; index++) {
                double angle = (360d / 64d) * index;
                Point2D poc = getPointOnCircle(angle, 100 - 4);
                Rectangle2D box = new Rectangle2D.Double(midX + poc.getX() - 2, midY + poc.getY() - 2, size.width, size.height);
                g2d.draw(box);
            }
            g2d.dispose();
        }

        protected Point2D getPointOnCircle(double degress, double radius) {
            double rads = Math.toRadians(degress - 90); // 0 becomes the top

            return new Point2D.Double(Math.cos(rads) * radius, Math.sin(rads) * radius);
        }
    }
}

所以,現在,你應該意識到我的“正方形”是正方形,而不是像你的“菱形”形狀。 這是你必須開始做一些工作的地方。

如果我正在解決這個問題,我可能會想創建一個自定義形狀,或者對box應用 45 度變換並將其轉換為 position 以渲染它或將整個結果旋轉 45 度,但這帶來了一個完整的包其他問題取決於你想用它做什么

這是一種方法(其中大部分是用於設置包含框架和面板的樣板)。 它使用sine and cosine方法來計算unit圓的點。 然后通過首先乘以所需較大圓的radius然后通過添加center x,y偏移量將其在面板中居中來調整這些點。

它包含的唯一真正特別的東西是 1) 保證外圓之間的間距為它們的直徑之一。 因此,如果圈數減少,則尺寸會增加。 這可以根據您的需要進行調整。 2) 我使用RenderingHints在視覺上平滑曲線。 最后 3) 我添加了一個帶有任意限制的簡單WheelListener ,這樣您就可以在上下移動鼠標滾輪時看到變化。 這會修改NCIRCLES (不應該對常量做的事情),然后重新繪制面板。 它很容易被移除。

public class CircleBorder extends JPanel {

    JFrame frame = new JFrame("Circle Border");
    static int BIG_RADIUS = 200;
    static int NCIRCLES = 60;
    static int WIDTH = 500;
    static int HEIGHT = 500;

    public static void main(String[] args ) {
        SwingUtilities.invokeLater(()->new CircleBorder().start());
    }
    public void start() {
     addMouseWheelListener((we)-> {
           int rot = we.getWheelRotation();
           if (NCIRCLES < 70 && rot > 0 || NCIRCLES > 7 && rot < 0) {
               NCIRCLES += rot;
           }
              
           repaint();
       });
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.add(this);
       frame.pack();
       // center on screen
       frame.setLocationRelativeTo(null);
       frame.setVisible(true);
    }
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH,HEIGHT);
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        
        int centerX = WIDTH/2;
        int centerY = HEIGHT/2;
        
        double angleIncrement = 2*Math.PI/NCIRCLES;
        g2d.setColor(Color.RED);
        
        // the next two lines adjusts the little radius so that each
        // outer circle will be one diameter apart.
        int bigD = (int)(Math.PI*2*BIG_RADIUS);
        int littleRadius = bigD/(NCIRCLES*4);
        
        // compute the x and y coordinates of the center of the outer circles.
        // and iterate once around the circle based on the computed angle above
        // to draw the circumference.  The little radius is subtracted to ensure
        // the center of those circles lies on the generated outer circle.

        double angle = 0;
        for (int i = 0; i < NCIRCLES; i++) {
              int x = (int)(centerX + Math.cos(angle)*BIG_RADIUS) - littleRadius;
              int y = (int)(centerY + Math.sin(angle)*BIG_RADIUS) - littleRadius;
              g2d.fillOval(x,y,littleRadius*2,littleRadius*2);
              angle += angleIncrement;
        }
        
        g2d.dispose();
    }
}

感謝@MadProgrammer 的回答。 我將他的代碼與@WJS 使用 RenderingHints 的建議和我自己的想法結合起來,以下代碼對我有用。

package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

/**
 * Thanks to <a
 * href=https://stackoverflow.com/users/992484/madprogrammer>@MadProgrammer</a>
 * on StackOverflow for the geometry part (<a
 * href=https://stackoverflow.com/questions/70398744/java-awt-draw-elements-around-a-circle>Source
 * code</a>)
 */
public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setExtendedState(Frame.MAXIMIZED_BOTH);
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JComponent {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return getParent().getSize();
        }

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

            Graphics2D g2d = (Graphics2D) g.create();
            //Thanks to @WJS for the idea
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int midX = getWidth() / 2;
            int midY = getHeight() / 2;
            int min = Math.min(getHeight() / 2, getWidth() / 2);
            Dimension size = new Dimension(min / 20, min / 20);
            double minsize = Math.min(size.getHeight(), size.getWidth());
            double radius = min - minsize;

            g2d.setColor(Color.BLACK);
            for (int index = 0; index < 64; index++) {
                double angle = (360d / 64d) * index;
                double rads = Math.toRadians(angle - 90); // 0 becomes the top
                Point2D poc = new Point2D.Double(Math.cos(rads) * radius, Math.sin(rads) * radius);
                g2d.fillOval((int) (midX + poc.getX() - 2), (int) (midY + poc.getY() - 2), size.width, size.height);
            }
            g2d.dispose();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM